<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[reading, writing, rambling]]></title><description><![CDATA[Long overdue personal site revamp]]></description><link>http://katieleonard.ca</link><generator>GatsbyJS</generator><lastBuildDate>Thu, 14 Apr 2022 20:22:05 GMT</lastBuildDate><item><title><![CDATA[Resources for New Managers]]></title><description><![CDATA[I haven’t written much over the last two years because I have been pretty steeped in the adventure of becoming an engineering manager. My…]]></description><link>http://katieleonard.ca/blog/2022/220309-new-manager-resources/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2022/220309-new-manager-resources/</guid><pubDate>Wed, 09 Mar 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I haven’t written much over the last two years because I have been pretty steeped in the adventure of becoming an engineering manager. My organization has more than doubled in size over the last year, and I am now in the position of mentoring for other folk who are beginning their journey on the manager track. I realized that I have read a significant number of management and leadership books over the last few years, so I put together a list of my favourites that have helped me most along the way.&lt;/p&gt;
&lt;h3&gt;The Manager’s Path — Camille Fournier&lt;/h3&gt;
&lt;p&gt;Absolute MUST READ for anyone at the IC or Tech Lead level who is curious about entering leadership. Camille shares her journey from Senior Engineer to CTO, along with how expectations change along the way. I use this book as a reference, and whenever I feel I am ready to take on a bigger challenge I re-read the chapter for the next level up.&lt;/p&gt;
&lt;h3&gt;Resilient Management — Lara Hogan&lt;/h3&gt;
&lt;p&gt;Lara is a management coach and founder of &lt;a href=&quot;https://wherewithall.com/&quot;&gt;Wherewithall&lt;/a&gt;. Management can sometimes be more art than science, but Lara shares practical tactics that can be applied in the fuzziest of situations. I constantly refer to her Feedback Equation and Manager Voltron practices.&lt;/p&gt;
&lt;h3&gt;Difficult Conversations — Bruce Patton, et al&lt;/h3&gt;
&lt;p&gt;My first task as a new manager was to set clear expectations, and to provide feedback to engineers who weren’t meeting them. Delivering actionable, critical feedback that lands is a skill, and learning how to approach difficult conversations from a place of curiousity and collaboration has been invaluable to me in both my professional and personal life.&lt;/p&gt;
&lt;h3&gt;Becoming a Manager — Linda Hill&lt;/h3&gt;
&lt;p&gt;This book is not specific to software engineering management, and I was surprised to learn that the challenges you face when moving from IC to people manager are universal to a lot of professional disciplines. In particular, the myths vs reality&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Myth&lt;/th&gt;
&lt;th&gt;Reality&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Operative principle&lt;/td&gt;
&lt;td&gt;Authority&lt;/td&gt;
&lt;td&gt;Interdependence&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Key players&lt;/td&gt;
&lt;td&gt;Direct reports&lt;/td&gt;
&lt;td&gt;Include those outside your formal authority&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Source of power&lt;/td&gt;
&lt;td&gt;Formal authority&lt;/td&gt;
&lt;td&gt;Everything but formal authority&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Focus&lt;/td&gt;
&lt;td&gt;Managing 1:1&lt;/td&gt;
&lt;td&gt;Managing one-on-one &lt;em&gt;and&lt;/em&gt; leading the team&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Desired Outcome&lt;/td&gt;
&lt;td&gt;Control through compliance&lt;/td&gt;
&lt;td&gt;Commitment through empowerment&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Key challenges&lt;/td&gt;
&lt;td&gt;Cope with complexity&lt;/td&gt;
&lt;td&gt;Cope with complexity &lt;em&gt;and&lt;/em&gt; change&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Essential competencies&lt;/td&gt;
&lt;td&gt;Technical&lt;/td&gt;
&lt;td&gt;Technical, human, conceptual&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;Effective Delegation of Authority — Hassan Ossman&lt;/h3&gt;
&lt;p&gt;Scaling yourself is one of the bigger challenges of management, and it is easy to get into the habit of thinking “it will take me the same amount of time to explain as it will be to delegate it.” This may be true for simple tasks that sort well in the Eisenhower Decision Matrix:&lt;/p&gt;
&lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/901ea8deab793c75bef9c0d82df1c14d/6a5c3/eisenhower-matrix.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 72.15189873417721%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAOCAIAAACgpqunAAAACXBIWXMAABYlAAAWJQFJUiTwAAACKklEQVQoz3WSW4+aUBRG5///h2aSXh7GMZH0QdHR0cMAAgLeqgiDRaUe9Ah4PHjj3lTT6ZhMV3ayn1a+7C/7Lr8ly7I8zz3fH2vaeDyZze38/9xdVxLH2DD2hkEMI7iMMxgsTDnZm2esn7Ee7ozTdhKeyTXiRo7DEEuSx7K43fY57iR3loAxB3S6bcd+O8VishWSbft8cD+So4io6qBU6lNU4/7+tVJBgjgdPg3FB/XlW6f1RWh+tieVNNrdyNcjozDEsowFofP4KBUKRJIgy02HT/leHstFmfnqLZoJlq7JWZZmF/7dfFDVs6IghlkBEPd6iOMtrZHH/RNi9w5IdlJ2UKKTd5NMCHFdd4OQDhi98Wy2gAnAa6vVo2vSy/eVxSxNxpky0AQL/dlFtudvMcYIIULIHULINE0IHf6HzWsOr0FuvBT1daOjV2t1VemKkiwrakdWREleQrhyHAihYRie5/0tLEl7Fm52LdCdscNfoG+LmiOI4nw+K19QVcWyfu4wfvuFt8KyKI7Fyfqhwt0Xq58KlceqwA3tFgC1Wo2iqHK5TNM0z/P4IqfpbWFRFPdneOSEpYZMPSvjVSzpKwAYqvSHer1eLBabzWYQBDfJb7I63SrWrjsL1Bnpzvf8CALAcCxbrVZZlqVpWhRFQsgHcpqm0A2gF0A3sDc7G2FriTRtghBar9cIoc1m4zjO8Xj84LffczweDENfzGeapo1GI9/336e9l38DPevumnMKykUAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;eisenhower matrix&quot; title=&quot;eisenhower matrix&quot; src=&quot;/static/901ea8deab793c75bef9c0d82df1c14d/f058b/eisenhower-matrix.png&quot; srcset=&quot;/static/901ea8deab793c75bef9c0d82df1c14d/c26ae/eisenhower-matrix.png 158w,
/static/901ea8deab793c75bef9c0d82df1c14d/6bdcf/eisenhower-matrix.png 315w,
/static/901ea8deab793c75bef9c0d82df1c14d/f058b/eisenhower-matrix.png 630w,
/static/901ea8deab793c75bef9c0d82df1c14d/40601/eisenhower-matrix.png 945w,
/static/901ea8deab793c75bef9c0d82df1c14d/78612/eisenhower-matrix.png 1260w,
/static/901ea8deab793c75bef9c0d82df1c14d/6a5c3/eisenhower-matrix.png 1646w&quot; sizes=&quot;(max-width: 630px) 100vw, 630px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
&lt;p&gt;…but you should delegate responsibilities, not tasks, and as with all things — the clearer the expectations are up-front, the better the outcome. This book is a quick read, but it made an outsized impact on my ability to scale — it also made me a leader who can grow the next generation of technical leaders.&lt;/p&gt;
&lt;h3&gt;Other Resources&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://review.firstround.com/this-90-day-plan-turns-engineers-into-remarkable-managers&quot;&gt;90-day plan to turn an engineer into an amazing manager&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://wherewithall.com/resources/First-One-on-One-Questions.pdf&quot;&gt;First 1:1 questions — Lara Hogan&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/kuchin/awesome-cto#management&quot;&gt;Awesome-CTO&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[So, You Want to Go to Code School!]]></title><description><![CDATA[I made a career change decision in 2013. I had been working as a lab technician at a biotech startup doing cancer and brain disorder…]]></description><link>http://katieleonard.ca/blog/2021/210417-so-you-want-to-go-to-code-school/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2021/210417-so-you-want-to-go-to-code-school/</guid><pubDate>Sat, 17 Apr 2021 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I made a career change decision in 2013. I had been working as a lab technician at a biotech startup doing cancer and brain disorder research for 7 years, and had taken a certificate at nightschool to learn to program. Getting that first job in software development was hard, even with a certificate under my belt, so I decided to go to code school to focus on learning a web development framework. Code schools were relatively new in 2013, and what the industry lacked in organization it more than made up for in enthusiasm.&lt;/p&gt;
&lt;p&gt;Code schools solve all kinds of challenges for the tech industry: not all problems in software require a CS degree; every industry requires software to function, driving unprecedented demand for programming skills; and career changers like myself can bypass trapdoors, which increases diversity. Getting accepted to a code school program gains you entry to a whole new world, but it can be hard to navigate without a guide.&lt;/p&gt;
&lt;p&gt;Two years after graduating the program and working in the industry, I wrote the guide I would have liked to have had. “So, You Want to Go to Code School” includes everything I learned from the moment I decided to make the change through my first two years as a software developer. While I wrote this guide in 2015, and code schools have evolved considerably, I think there is still some value to be gleaned for early software developer careers.&lt;/p&gt;
&lt;p&gt;One note before you dive in — the url for the book (codeschoolbook.com) is no longer mine 😀. I wish the new owners luck with their kickstarter campaign! Also, I am open to feedback — &lt;a href=&quot;https://katieleonard.ca/contact&quot;&gt;checkout my contact form or drop me an email&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Good luck on your journey!&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;/44c5ecede68ac772ff0405669b9357d0/codeschoolbook.pdf&quot; download&gt;So, You Want to Go to Code School! Download&lt;/a&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Success With Snippets]]></title><description><![CDATA[Many engineers use code snippet managers to quickly auto-complete repetitious and predictable keystrokes. I have used Dash for many years to…]]></description><link>http://katieleonard.ca/blog/2021/210404-success-with-snippets/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2021/210404-success-with-snippets/</guid><pubDate>Mon, 05 Apr 2021 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Many engineers use code snippet managers to quickly auto-complete repetitious and predictable keystrokes. I have used &lt;a href=&quot;https://kapeli.com/dash&quot;&gt;Dash&lt;/a&gt; for many years to autocomplete test cases, &lt;code class=&quot;language-text&quot;&gt;import React from &apos;react&apos;&lt;/code&gt; and to correct things I always misspell (in case you ever see it, my full name is Kather&lt;strong&gt;ine&lt;/strong&gt; not Kather&lt;strong&gt;ing&lt;/strong&gt; — why do I do this?).&lt;/p&gt;
&lt;p&gt;Having learned a lot of strategies for effective communication, I started building snippets to keep them top of mind. These snippets help me to focus my thoughts, keep my audience in mind, and help me stop procrastinating. Whenever I had to create a presentation, write up a technical proposal, or to deliver constructive feedback.&lt;/p&gt;
&lt;h2&gt;Creating Presentations: Think of Your Audience First&lt;/h2&gt;
&lt;p&gt;I attended a workshop on “executive presence”. It was information dense, and I learned a tremendous amount about how to optimize your message for your audience. Much of the workshop centered on public speaking, so I also learned how to connect with your audience during a presentation, how to manage Q&amp;#x26;A, and how to build and deliver a slide deck that enhances your message rather than distracts from it. Knowing that I would quickly forget many of these strategies, I distilled them into a snippet. I type &lt;code class=&quot;language-text&quot;&gt;`start&lt;/code&gt;, and my blank document is replaced with this template:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;--------------------------------------
Goals
Audience: name your stakeholders and their currency
3 key takeaways
Call to action
--------------------------------------
Tell them what you will tell them.
Tell them.
Tell them what you told them.
--------------------------------------
Evoke emotion
Cut to the point
Arrange message for memorability
--------------------------------------
1. Agreement: provides a baseline and direction; big picture
2. Context: What is the problem and what is the pain? Brings the big picture closer
3. Story: narrative demonstrating a change from pain to no-pain
4. Connections: use analogies to explain and metaphors to highlight
5. Conclusion: summarize what was learned, and make your call to action.
--------------------------------------
Visuals should accentuate, reinforce, and repeat your message
--------------------------------------
Don&apos;t answer the question &quot;what is X?&quot;,
  answer the question &quot;why should I care about X?&quot;
Going from less understanding to more understanding,
  don&apos;t be afraid to cover the basics:
  it accounts for everyone and validates the experts.
---------------------------------------&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This snippet ensures that I start with the goal in mind, that I aim my content at the right audience, and that my takeaways are clear.&lt;/p&gt;
&lt;h2&gt;Writing Technical Proposals: Exploring Multiple Options&lt;/h2&gt;
&lt;p&gt;One of the common asks for a technical lead on a software team is to provide technical estimates and options for upcoming projects. These requests happen so frequently, I came up with a formula that made my communication clear and my results consistent. I type `&lt;code class=&quot;language-text&quot;&gt;tech&lt;/code&gt; and my blank document is replaced by this template:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;# Technical Problem Writeup Template

## Problem

High level overview of the problem.
Determine your audience.
Summarize the problem at the right level of detail --
  * Executives: describe the WHY in terms of risks to the
      roadmap, team, reliability.
      Do not include technical detail.
  * PMs: describe the above but with some technical detail
  * Engineers: describe the technical challenges

## Options

* Include at least three options, one of which is to do nothing.
* List Pros and Cons of each option and be specific:
  “link from X to Y requires an extra query which will
  impact performance” rather than “bad customer experience.”
* Make a recomendation
* Include a level of effort
* Considered and Rejected
  * If any options were rejected, itemize and bullet
    point the reasons they were rejected

## Resources

Links that didn’t fit into the Details section,
  including other documents that describe or
  reference the problem at hand.&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Using this snippet has leveled up my ability to communicate technical trade-offs to the right audience at the right level. I have been using it for almost two years, and I believe this strategy is one of the main accelerators of my career from senior enginer to architect.&lt;/p&gt;
&lt;h2&gt;Delivering Constructive Feedback: Stick to the Facts and Stay Curious&lt;/h2&gt;
&lt;p&gt;Delivering constructive feedback is hard, and there are more ways to do it wrong than to do it right, which is probably why we avoid it. After reading &lt;a href=&quot;https://resilient-management.com/&quot;&gt;Resilient Management&lt;/a&gt; by Lara Hogan, I learned some incredible strategies for how to construct feedback that emphasizes empathy and improves the odds that your feedback will land as you intend. It doesn’t nearly do justice to Hogan’s &lt;a href=&quot;https://larahogan.me/blog/feedback-equation/&quot;&gt;beautiful blog&lt;/a&gt;, but when I need to carefully consider the impact of the feedback I need to deliver, I type `&lt;code class=&quot;language-text&quot;&gt;feedback&lt;/code&gt; and my blank document is replaced by this template:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;-------------------------
## Feedback equation
Facts + impact + open question = good feedback

Keep asking &quot;what is the impact of THAT&quot; until you have the real impact.

## Frame the impact in terms of what THEY care about:

* Belonging? It makes you seem unapproachable...
* Improvement/progress? It slows down the project...
* Choice? It reduces our options...
* Equality/fairness? Others have to pick up the slack...
* Predictability? It disrupts the routine...
* Significance/status? It makes us lose trust...
-------------------------
## Open questions

* What are you optimizing for?
* What are you hoping to accomplish?&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This snippet ensures that I am framing my constructive feedback in a way that will be most effective for the person receiving it. I consider their core needs, stick to the facts, and remain open to learning more about how they perceive things.&lt;/p&gt;
&lt;p&gt;As a brief aside, I recently read &lt;a href=&quot;https://www.amazon.com/Difficult-Conversations-Discuss-What-Matters/dp/0143118447&quot;&gt;“Difficult Conversations”&lt;/a&gt; by Douglas Stone, Bruce Patton, and Sheila Heen. They say very wisely that if you think you have all the information about a situation, then you are not ready to have a difficult conversation. This snippet is a good place to stick a reminder to get and stay curious about where someone else is coming from:  I think I will add it so that I will remember it for next time.&lt;/p&gt;
&lt;h2&gt;Snippet managers are useful for more than just code completion&lt;/h2&gt;
&lt;p&gt;I use Dash, but there are many different &lt;a href=&quot;https://dev.to/tomlangdon/5-code-snippet-managers-that-will-change-the-way-you-write-code-10ml#:~:text=What%20Is%20A%20Code%20Snippet,organised%20and%20ready%20to%20use.&quot;&gt;code snippet managers&lt;/a&gt; out there. Find one that works for you and you will bring your written communication to the next level.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;In case you are curious, here is the result of the snippet template I used to write this blog post:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;--------------------------------------
Goal: To persuade the reader that snippets are useful outside of the code editor.

Audience: Software Engineers and Engineering Managers

3 key takeaways:

* use snippets to remind yourself what questions to ask
* use snippets to craft and focus your communication
* use snippets to break through writers block through prompts and structure

Call to action:

Use Dash or some other snippet manager to remind you of strategies you tend to forget.
--------------------------------------
...

Don&apos;t answer the question &quot;what is X?&quot;, answer the question &quot;why should I care about X?&quot;

Why should they care about using snippets?
Snippets are a means to an end: providing consistent, clear communication builds trust with your peers and managers.
Career growth beyond an individual contributor role requires strong communication skills.
Building trust with your organization is good for your career growth.
---------------------------------------&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</content:encoded></item><item><title><![CDATA[Multiple Content Sources in Gatsby]]></title><description><![CDATA[Tell Gatsby about your new content Using the  plugin, identify your new collection of content and give it a reference name. Add this to the…]]></description><link>http://katieleonard.ca/blog/2020/201024-multiple-content-sources-gatsby/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2020/201024-multiple-content-sources-gatsby/</guid><pubDate>Sat, 24 Oct 2020 00:00:00 GMT</pubDate><content:encoded>&lt;h3&gt;Tell Gatsby about your new content&lt;/h3&gt;
&lt;p&gt;Using the &lt;code class=&quot;language-text&quot;&gt;gatsby-source-filesystem&lt;/code&gt; plugin, identify your new collection of content and give it a reference name.&lt;/p&gt;
&lt;p&gt;Add this to the plugins section of your gatsby-config.js:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;  &lt;span class=&quot;token literal-property property&quot;&gt;plugins&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token literal-property property&quot;&gt;resolve&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;gatsby-source-filesystem&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token literal-property property&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token literal-property property&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;__dirname&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;/content/cheatsheets&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token literal-property property&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;cheatsheets&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;Tell Gatsby to add some node meta-data&lt;/h3&gt;
&lt;p&gt;When Gatsby is creating nodes out of your markdown files, tell it to detect what collection it is a part of and add that information to the node metadata:&lt;/p&gt;
&lt;p&gt;Add this to your gatsby-node.js &lt;code class=&quot;language-text&quot;&gt;onCreateNode&lt;/code&gt; method:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;exports&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function-variable function&quot;&gt;onCreateNode&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; node&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; actions&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; getNode &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; createNodeField &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; actions

  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;node&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;internal&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;type &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;MarkdownRemark&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; collection &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getNode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;node&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;parent&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;sourceInstanceName

    &lt;span class=&quot;token function&quot;&gt;createNodeField&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token literal-property property&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;collection&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      node&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token literal-property property&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; collection
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;With those two pieces in place, you can group your content by the collection they appear in:&lt;/p&gt;
&lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/c0da35d5921fcc3d63d63626871fbfb5/de9fe/grouped-by-collection.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 88.60759493670886%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAASCAIAAADUsmlHAAAACXBIWXMAABYlAAAWJQFJUiTwAAABtUlEQVQ4y42Si47jIAxF+/9fueqqaZ6AMX5AgIzcdGd2uxpNrSsUEMePGy4AgIjTvNyG+7ys07SM4zTcx9sw3sdpnOZPnVvnQ4A4Oz+M0+V6/T2Ok3POW7gQzjVs2xa8XYQQoi2n7MyOHx+XnFWkxphTKpByiFry3rV22VttTLRObtrAR0rMJMqizEoPXUSYpDjgvdRaW9lbb/1ordd2HIeqeki3JWyAxMpJmIXPFGKwtN7nwInL8V+I2qXZ4XXyMSA5tAb0D0xEtTbSsrdWe+9H/xfOxAyJAxAblj/LGsxMmDKiIuWAKlTqXlve676fbS8OFo+q+kI+K+dSfZS625C99ad6P2FAGlZYw6Nhlr9TWOXejzkw6fcze7yOPm5gMwMR8hNOKdVay17PUi+hqok4xBSR6VQk8/zL7daOb0JUiWV2cVgB46tnl1LK8X2c8BZwXCNukXxiSBQSI/0Mq8HsIcHjfZnshcm7lVlkcvHX6MFFAvpK8QacicUqRzKfI5FP5ra+A4vNvHi8bxHx0XnJ5pnpnbZZVo/3BeIWk0PySJDII5P8DCdiBymez4vEfrKNbdsPJ8ITHXcH3GUAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;grouped by collection&quot; title=&quot;grouped by collection&quot; src=&quot;/static/c0da35d5921fcc3d63d63626871fbfb5/f058b/grouped-by-collection.png&quot; srcset=&quot;/static/c0da35d5921fcc3d63d63626871fbfb5/c26ae/grouped-by-collection.png 158w,
/static/c0da35d5921fcc3d63d63626871fbfb5/6bdcf/grouped-by-collection.png 315w,
/static/c0da35d5921fcc3d63d63626871fbfb5/f058b/grouped-by-collection.png 630w,
/static/c0da35d5921fcc3d63d63626871fbfb5/40601/grouped-by-collection.png 945w,
/static/c0da35d5921fcc3d63d63626871fbfb5/78612/grouped-by-collection.png 1260w,
/static/c0da35d5921fcc3d63d63626871fbfb5/de9fe/grouped-by-collection.png 2146w&quot; sizes=&quot;(max-width: 630px) 100vw, 630px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
&lt;p&gt;If you are using the gatsby blog template like I am, you can fix some of those console errors by adding the new collection field to your schema:&lt;/p&gt;
&lt;p&gt;In your gatsby-node.js file:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;exports&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function-variable function&quot;&gt;createSchemaCustomization&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; actions &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; createTypes &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; actions

  &lt;span class=&quot;token function&quot;&gt;createTypes&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;
...
    type MarkdownRemark implements Node {
      frontmatter: Frontmatter
      fields: Fields
    }
...
    type Fields {
      slug: String
      collection: String
    }
  &lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;Update createPages to generate your collections&lt;/h3&gt;
&lt;p&gt;Start with a config object that describes each collection:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;COLLECTIONS&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;blog&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;hasDetailPage&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;needsPagination&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;indexComponent&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; path&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;resolve&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;./src/templates/blog-list.js&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;detailComponent&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; path&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;resolve&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;./src/templates/blog-post.js&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;cheatsheets&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;hasDetailPage&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;indexComponent&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; path&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;resolve&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;./src/templates/cheatsheet-list.js&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;detailComponent&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; path&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;resolve&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;./src/templates/blog-post.js&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In order to build your collection pages, you need a generic function that will work for each of your collections. In my case, I wanted a collection of blog posts (a paginated index page and post page for each blog), and a collection of cheatsheets (a non-paginated index page and post page for each cheatsheet).&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;buildCollectionPages&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  nodes&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  createPage&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  name&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  needsPagination&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  hasDetailPage&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  indexComponent&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  detailComponent&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; posts &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;filterNodes&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;nodes&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;needsPagination&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// Paginated index pages&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; numPages &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Math&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;ceil&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;posts&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;MAX_POSTS_PER_PAGE&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    Array&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; numPages &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;forEach&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;_&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; i&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; currentPage &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; previous &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; numPages &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; currentPage &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; next &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; i

      &lt;span class=&quot;token function&quot;&gt;createPage&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token literal-property property&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;name&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;name&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;/page_&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;currentPage&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token literal-property property&quot;&gt;component&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; indexComponent&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token literal-property property&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
          &lt;span class=&quot;token literal-property property&quot;&gt;limit&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;MAX_POSTS_PER_PAGE&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
          &lt;span class=&quot;token literal-property property&quot;&gt;skip&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;MAX_POSTS_PER_PAGE&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
          numPages&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
          currentPage&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
          next&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
          previous&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// Single index page&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;createPage&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token literal-property property&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;name&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token literal-property property&quot;&gt;component&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; indexComponent&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// Generate detail pages for each post in the collection&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;hasDetailPage&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    posts&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;forEach&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;post&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; index&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; previous &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; index &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; posts&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; posts&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;index &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; next &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; index &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; posts&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;index &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; slug &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; post&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;fields

      &lt;span class=&quot;token function&quot;&gt;createPage&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token literal-property property&quot;&gt;component&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; detailComponent&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token literal-property property&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; slug&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token literal-property property&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
          slug&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
          previous&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
          next&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Query for all your data, ensuring that you fetch the collection field as well. Loop over your COLLECTIONS, and build the pages for each one by passing in the retrieved data:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;createCollectionPages&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; graphql&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; actions&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; reporter &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; createPage &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; actions

  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;graphql&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;
    query {
      postData: allMarkdownRemark(
        sort: { fields: [frontmatter___date], order: DESC }
      ) {
        nodes {
          fields {
            collection
            slug
          }
          frontmatter {
            title
          }
        }
      }
    }
  &lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;token constant&quot;&gt;COLLECTIONS&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;forEach&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;collection&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;buildCollectionPages&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;collection&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token literal-property property&quot;&gt;nodes&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;postData&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;nodes&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      createPage&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

module&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;exports &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; createCollectionPages&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The &lt;code class=&quot;language-text&quot;&gt;{ graphql, actions, reporter }&lt;/code&gt; object is passed in to the createPages API from Gatsby. We call &lt;code class=&quot;language-text&quot;&gt;createCollectionPages&lt;/code&gt; in an async context in gatsby-node.js &lt;code class=&quot;language-text&quot;&gt;createPages&lt;/code&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; createCollectionPages &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;./gatsby-helpers/create-collection-pages&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

exports&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function-variable function&quot;&gt;createPages&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; graphql&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; actions&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; reporter &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;createCollectionPages&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; graphql&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; actions&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; reporter &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;If you aren’t generating any other types of pages, you can make it even more succinct:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;exports&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;createPages &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; createCollectionPages&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Awesome.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Styling Active Links in Gatsby]]></title><description><![CDATA[When Gatsby generates static pages, it helpfully adds a tag to the active nav item: This makes it easy to add a style to the active nav so…]]></description><link>http://katieleonard.ca/blog/2020/201024-styling-active-link-gatsby/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2020/201024-styling-active-link-gatsby/</guid><pubDate>Sat, 24 Oct 2020 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;When Gatsby generates static pages, it helpfully adds a tag to the active nav item:&lt;/p&gt;
&lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/17bced89fdecd6730d835ec64d09b25e/d4b10/aria-current.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 79.74683544303798%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAQCAIAAACZeshMAAAACXBIWXMAABYlAAAWJQFJUiTwAAACOUlEQVQoz5VTzW7UMBDOg3HkIfooiGcpR3oAFcEBJFpxQAKppSmrVmxhtYFN4sSOHSdObCfZJLYHJXRbCqgSn0ajGWt+vvHYntvBWgOTtjv3Gs7uAmYx1tlZnHMe7LDt+5hQC/+BKdk5BwCvDvYf7T1cLD7NJ7bkFU14lvJGdwDQdGPV9HXbs7rlstPdsEu2U78XhweP9x68OT4GgKEfrz6gxVFw9W6NgxIAvqXi/Ee+TMqLiC9RkVXtnc6ybT+enDbd1McMtq+NKMzrxWg6ex/tf2IuCC8DWIlb98/kZCGjTzXyJfJVeFrFZ5OBfBX7KvElOlPP3+rIV8m5in2JZh3PwbEvvYwwmuUxoqs1yplIES7yMk0Iz8sUZQXNV3H5/oLUvMAJpSTPKY9DxFlZlbXXiKZKKSd5yepel50stnXeKF3X/XwbE92NcKKbDLeTa9qtavma9Up3emia8Wa432c0Fqiy9q+xPQdOclmTjEXrJBKCS5wqmmlGOMNllRcbXES0W+EBsT6vRqyAt9elvbmwEaRSacgxjiJNSNM1W3DNsG2LSu/749NL++yLPbi0J7HZP7dPPhu9dberGoZRF9p0WzMTbw1ccggqGCxYgGFuZBz8Yn4ztqeU0jMKVuQJKVk2SHZ0IQ7PuBZUlJJzyVmdz8KYlEIoUdBC81J5hJAsyyilSZx8XS7DIAiD79EGCZqSFMUxiSIcRZMOQxxGGKdpgtB6k4Ux8XbvyWmhNVNjZ+DuPu75VT8BiEmG401T7xwAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;aria current&quot; title=&quot;aria current&quot; src=&quot;/static/17bced89fdecd6730d835ec64d09b25e/f058b/aria-current.png&quot; srcset=&quot;/static/17bced89fdecd6730d835ec64d09b25e/c26ae/aria-current.png 158w,
/static/17bced89fdecd6730d835ec64d09b25e/6bdcf/aria-current.png 315w,
/static/17bced89fdecd6730d835ec64d09b25e/f058b/aria-current.png 630w,
/static/17bced89fdecd6730d835ec64d09b25e/40601/aria-current.png 945w,
/static/17bced89fdecd6730d835ec64d09b25e/78612/aria-current.png 1260w,
/static/17bced89fdecd6730d835ec64d09b25e/d4b10/aria-current.png 1394w&quot; sizes=&quot;(max-width: 630px) 100vw, 630px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
&lt;p&gt;This makes it easy to add a style to the active nav so that your users always know what page they are on. Since I am using styled components, here is how I am styling the nav:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; StyledLink &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;styled&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Link&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;
  padding: 0.5rem;
  text-decoration: none;
  border: solid transparent;
  border-width: 0 0 thick 10px;

  &amp;amp;:hover,
  &amp;amp;[aria-current=&quot;page&quot;] {
    color: var(--purple);
    border: solid var(--purple);
    border-width: 0 0 thick 10px;
    border-color: transparent var(--purple) var(--purple) transparent;
    border-radius: 0 0 20px 0;
  }
&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The hover styles now persist when someone clicks on a link!&lt;/p&gt;
&lt;p&gt;Awesome.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Active Associations]]></title><description><![CDATA[Working in a legacy code base, you will come across a lot of join tables and belongs-to-through complexity.
You can visualize these…]]></description><link>http://katieleonard.ca/blog/2020/201022-active-associations/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2020/201022-active-associations/</guid><pubDate>Thu, 22 Oct 2020 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Working in a legacy code base, you will come across a lot of join tables and belongs-to-through complexity.
You can visualize these associations using an ERD, or you can find them in the console by using&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ruby&quot;&gt;&lt;pre class=&quot;language-ruby&quot;&gt;&lt;code class=&quot;language-ruby&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;ModelName&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;reflect_on_all_associations&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;map&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;token symbol&quot;&gt;:name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;For example, I am testing out the Thredded forum gem, and found a lot of complex join tables to navigate.
I wanted to find all the ways I could access data in the UserTopicFollows join table:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ruby&quot;&gt;&lt;pre class=&quot;language-ruby&quot;&gt;&lt;code class=&quot;language-ruby&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; Thredded&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;UserTopicFollow&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;reflect_on_all_associations&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;map&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;token symbol&quot;&gt;:name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token symbol&quot;&gt;:user&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token symbol&quot;&gt;:topic&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;So, I can get there through a Topic. That makes sense, since it is a join table.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ruby&quot;&gt;&lt;pre class=&quot;language-ruby&quot;&gt;&lt;code class=&quot;language-ruby&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; Thredded&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;Topic&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;reflect_on_all_associations&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;map&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;token symbol&quot;&gt;:name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token symbol&quot;&gt;:last_user&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
 &lt;span class=&quot;token symbol&quot;&gt;:slugs&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
 &lt;span class=&quot;token symbol&quot;&gt;:user&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
 &lt;span class=&quot;token symbol&quot;&gt;:messageboard&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
 &lt;span class=&quot;token symbol&quot;&gt;:user_detail&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
 &lt;span class=&quot;token symbol&quot;&gt;:posts&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
 &lt;span class=&quot;token symbol&quot;&gt;:first_post&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
 &lt;span class=&quot;token symbol&quot;&gt;:last_post&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
 &lt;span class=&quot;token symbol&quot;&gt;:topic_categories&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
 &lt;span class=&quot;token symbol&quot;&gt;:categories&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
 &lt;span class=&quot;token symbol&quot;&gt;:user_read_states&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
 &lt;span class=&quot;token symbol&quot;&gt;:user_follows&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
 &lt;span class=&quot;token symbol&quot;&gt;:followers&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
 &lt;span class=&quot;token symbol&quot;&gt;:likes&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And I can get to Posts from Topics. That also makes sense, since Posts belong to Topics.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ruby&quot;&gt;&lt;pre class=&quot;language-ruby&quot;&gt;&lt;code class=&quot;language-ruby&quot;&gt;&lt;span class=&quot;token number&quot;&gt;2.7&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;.0&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;001&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; Thredded&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;Post&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;reflect_on_all_associations&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;map&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;token symbol&quot;&gt;:name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
 &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token symbol&quot;&gt;:user&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token symbol&quot;&gt;:messageboard&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token symbol&quot;&gt;:postable&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token symbol&quot;&gt;:user_detail&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token symbol&quot;&gt;:moderation_records&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token symbol&quot;&gt;:user_notifications&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token symbol&quot;&gt;:last_moderation_record&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;It doesn’t look like I can get back to Topic from Post, however.
Since a Post belongs to a Topic, I expected that association to be in the list.
That &lt;code class=&quot;language-text&quot;&gt;:postable&lt;/code&gt; association was unexpected as well, and I couldn’t find a Postable model.
It turns out that &lt;code class=&quot;language-text&quot;&gt;postable&lt;/code&gt; is an alias for Topic in a UserTopicFollow join table:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ruby&quot;&gt;&lt;pre class=&quot;language-ruby&quot;&gt;&lt;code class=&quot;language-ruby&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Thredded&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UserTopicFollow&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; ActiveRecord&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;Base
  &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
  alias_attribute &lt;span class=&quot;token symbol&quot;&gt;:postable&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token symbol&quot;&gt;:topic&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;While my head is still spinning a bit.. I found what I needed to get unblocked. 🙃&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Using Styled Components With Gatsby]]></title><description><![CDATA[The styles assigned with styled components are applied at javascript runtime. They generate a css stylesheets specific to your component and…]]></description><link>http://katieleonard.ca/blog/2020/201010-using_styled_components_with_gatsby/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2020/201010-using_styled_components_with_gatsby/</guid><pubDate>Sat, 10 Oct 2020 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;The styles assigned with styled components are applied at javascript runtime. They generate a css stylesheets specific to your component and inject it into the head. When you use styled components for rendering things like a nav or layout, there is a strong possibility that your content will arrive on the page before the CSS required to style it, causing a usually brief but very disconcerting flash of unstyled content:&lt;/p&gt;
&lt;img src=&quot;/d24d473f796cb76d45241ad2cd13bd37/unstyled-content.gif&quot; style=&quot;border-radius: 20px&quot;&gt;
&lt;p&gt;This can be solved by ensuring that Gatsby inserts your important styles inline with your html when it generates the page.&lt;/p&gt;
&lt;h3&gt;Step one: ensure that gatsby knows you are using styled components&lt;/h3&gt;
&lt;p&gt;Follow the instructions on the &lt;a href=&quot;https://www.gatsbyjs.com/docs/styled-components/&quot;&gt;Gatsby styled-components page&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ &lt;span class=&quot;token function&quot;&gt;npm&lt;/span&gt; i gatsby-plugin-styled-components&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And import the plugin to your gatsby-config:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;module&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;exports &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;plugins&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
    &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;gatsby-plugin-styled-components&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;Step two: add important styles to a GlobalStyle component&lt;/h3&gt;
&lt;p&gt;Inside your styles folder, create a &lt;code class=&quot;language-text&quot;&gt;GlobalStyles.js&lt;/code&gt; file and add your important styles like so:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; createGlobalStyle &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;styled-components&quot;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; GlobalStyles &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; createGlobalStyle&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;
...
  nav.custom-nav {
    margin-bottom: 3rem;

    ul {
      margin: 0;
      padding: 0;
      text-align: center;
      list-style: none;

      display: grid;
      grid-template-columns: auto 1fr 1fr 1fr;
      grid-gap: 2rem;
      align-items: center;
    }
  }
...
&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;Step three: Inline your GlobalStyles in your Layout component&lt;/h3&gt;
&lt;p&gt;Ensure that your most important styles will be inlined on every page:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; GlobalStyles &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;../styles/GlobalStyles&apos;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;default&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;Layout&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
      &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;GlobalStyles &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
      &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;div className&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;site&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
        &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;nav className&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;custom-nav&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
          &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;ul&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
            &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
          &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;ul&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
        &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;nav&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
        &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
      &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;div&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;div&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</content:encoded></item><item><title><![CDATA[Swoosh underline on hover (CSS)]]></title><description><![CDATA[As I mentioned in my last post, I’m finally working on reskinning my personal blog and using Gatsby to build the site. I am also taking Wes…]]></description><link>http://katieleonard.ca/blog/2020/201004-swoosh-underline-on-hover/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2020/201004-swoosh-underline-on-hover/</guid><pubDate>Sun, 04 Oct 2020 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;As I mentioned in my last post, I’m finally working on reskinning my personal blog and using Gatsby to build the site. I am also taking &lt;a href=&quot;https://mastergatsby.com/&quot;&gt;Wes Bos’s Master Gatsby course&lt;/a&gt; and realized that menus don’t need to be as static and boring as they historically have been. Since you can do almost anything with CSS, I decided to attempt a swoosh underline on hover, and it was more challenging than I expected.&lt;/p&gt;
&lt;p&gt;Basic layout of the Nav is pretty dry markup:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;&amp;lt;ul&gt;
  &amp;lt;li&gt;
    &amp;lt;Link to=&quot;/about&quot;&gt;about&amp;lt;/Link&gt;
  &amp;lt;/li&gt;
  &amp;lt;li&gt;
    &amp;lt;Link to=&quot;/projects&quot;&gt;projects&amp;lt;/Link&gt;
  &amp;lt;/li&gt;
  &amp;lt;li&gt;
    &amp;lt;Link to=&quot;/contact&quot;&gt;contact&amp;lt;/Link&gt;
  &amp;lt;/li&gt;
&amp;lt;/ul&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Using styled-components, I could experiment with different colors and treatments on the fly. You can see the result on the page above, but here is how I landed on the swoosh:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;const StyledNav = styled.nav`
  display: flex;
  justify-content: flex-end;

  ul {
    list-style-type: none;
    display: flex;

    li {
      margin-right: 1rem;
      font-size: 1.25rem;

      a {
        padding: 0.5rem;
        text-decoration: none;
        border: solid transparent;
        border-width: 0 0 thick 10px;
      }

      a:hover {
        color: purple;
        border: solid purple;
        border-width: 0 0 thick 10px;
        border-color: transparent purple purple transparent;
        border-radius: 0 0 20px 0;
      }
    }
  }
`&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Wrap the dry unordered list with the &lt;StyledNav&gt; component, and voila! The key to not having janky hover styles is to ensure that your padding, margin, and borders are consistent between hover and non-hover states. Using &lt;code class=&quot;language-text&quot;&gt;transparent&lt;/code&gt; as the color helps with the borders width.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Opaque background images]]></title><description><![CDATA[I’m finally working on reskinning my personal blog and really enjoying the Gatsby ecosytem. I wanted to add a little color to the…]]></description><link>http://katieleonard.ca/blog/2020/201003-background-images/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2020/201003-background-images/</guid><pubDate>Sat, 03 Oct 2020 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I’m finally working on reskinning my personal blog and really enjoying the Gatsby ecosytem. I wanted to add a little color to the boilerplate, and to demonstrate to all observers that my stylistic bent is solidly stuck in the 90s.&lt;/p&gt;
&lt;p&gt;Poking at the Gastby way of loading content, such as the avatar, it seems that the preferred way is to load the asset using graphql:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;query BioQuery {
  avatar: file(absolutePath: { regex: &quot;/profile-pic.jpg/&quot; }) {
    childImageSharp {
      fixed(width: 50, height: 50, quality: 95) {
        ...GatsbyImageSharpFixed
      }
    }
  }
  ...&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;It turns out that there is a plugin for everything in Gatsby, including &lt;a href=&quot;https://www.gatsbyjs.com/plugins/gatsby-background-image&quot;&gt;one for adding background images using react&lt;/a&gt;. Any front-end developer worth their salt would read those docs, get super excited about processing background images at runtime. I am not that developer. I used css.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;body::after {
  content: &quot;&quot;;
  background: url(../content/assets/splatter-background.png);
  background-size: contain;
  opacity: 0.2;
  top: 0;
  left: 0;
  bottom: 0;
  right: 0;
  position: absolute;
}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</content:encoded></item><item><title><![CDATA[Recursive Rendering and Event Bubbling]]></title><description><![CDATA[I have been working with dense tree structures recently, and rendering them using React. Trees lend themselves well to recursion, so I set…]]></description><link>http://katieleonard.ca/blog/2018/2018-04-01-rendering-recursion-and-event-bubbling/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2018/2018-04-01-rendering-recursion-and-event-bubbling/</guid><pubDate>Sun, 01 Apr 2018 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I have been working with dense tree structures recently, and rendering them using React. Trees lend themselves well to recursion, so I set about making a component that could render itself and all subsequent children with ease. I thought I was being mightily clever, until I tried to add some behaviour to my recursive component.&lt;!-- more --&gt; Things were not behaving as they should, and I was stumped for quite some time. When I finally stepped back from the trees to see the forest (pun intended), I had to step all the way back to HTML-101 to find the answer.&lt;/p&gt;
&lt;p&gt;Here is my clever component:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;default&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ListItem&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;PureComponent&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token function-variable function&quot;&gt;renderChildren&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token parameter&quot;&gt;arr&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;ul&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;arr&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;renderChild&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;ul&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token function-variable function&quot;&gt;renderChild&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token parameter&quot;&gt;item&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;ListItem &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;item&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;render&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; name&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; children &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
      &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;li&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;children &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;renderChildren&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;children&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
      &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;li&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;When called from the parent container with the root of the tree, this component will render all nodes of the tree as unordered lists of items:&lt;/p&gt;
&lt;img src=&quot;https://raw.githubusercontent.com/keighty/react-recursion/master/images/unordered-lists.png&quot;&gt;
&lt;p&gt;Of course, with very deep trees, it is useful to clear away visual noise by collapsing parts of the tree, so I added an &lt;code class=&quot;language-text&quot;&gt;onClick&lt;/code&gt; handler to each list item with children:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;default&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ListItem&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;PureComponent&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  state &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;showChildren&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token function-variable function&quot;&gt;onClick&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token parameter&quot;&gt;e&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;setState&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;showChildren&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;state&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;showChildren &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;render&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; name&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; children &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; showChildren &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;state&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
      &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;li onClick&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;onClick&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;children &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; showChildren &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;renderChildren&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;children&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
      &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;li&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Setting a &lt;code class=&quot;language-text&quot;&gt;showChildren&lt;/code&gt; state on the ListItem instance will hide parts of the list by simply not rendering them, rather than hiding them using traditional CSS. You can imagine my chagrin, then, when I clicked on an item, and the entire tree collapsed into the root:&lt;/p&gt;
&lt;img src=&quot;https://raw.githubusercontent.com/keighty/react-recursion/master/images/collapsed-lists.png&quot;&gt;
&lt;p&gt;Troubleshooting recursion is tricky. Was the state change leaking from one instance of ListItem to another? They should be independent instances, but what if they shared a state reference?&lt;/p&gt;
&lt;p&gt;Finally, I turned my suspicions on the click handler.&lt;/p&gt;
&lt;p&gt;I left the React docs behind and went back to &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Building_blocks/Events&quot;&gt;the primer&lt;/a&gt; on how the DOM handles events. This is where I found the answer to the overzealous-click problem — it wasn’t ocurring because of using recursion, it was happening because of event bubbling (:face-palm:).&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;[When a user clicks on a ListItem, t]he browser checks to see if the element that was actually clicked on has an onclick event handler registered on it in the bubbling phase, and runs it if so… &lt;strong&gt;Then it moves on to the next immediate ancestor element and does the same thing&lt;/strong&gt;, then the next one, and so on until it reaches the &amp;#x3C;html&gt; element.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Because there was a click handler registered on every list item, a click on any one of them would be handled by &lt;strong&gt;every one of them&lt;/strong&gt;.
Fortunately, Javascript-Events-101 also prescribes a solution: &lt;code class=&quot;language-text&quot;&gt;e.stopPropagation()&lt;/code&gt;, which stops the event from bubbling up the ancestry tree.&lt;/p&gt;
&lt;p&gt;My final &lt;code class=&quot;language-text&quot;&gt;onClick&lt;/code&gt; handler:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token function-variable function&quot;&gt;onClick&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token parameter&quot;&gt;e&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  e&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;stopPropagation&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; showChildren &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;state&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;setState&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;showChildren&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;showChildren &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And the nested result I wanted:&lt;/p&gt;
&lt;img src=&quot;https://raw.githubusercontent.com/keighty/react-recursion/master/images/proper-collapsing.png&quot;&gt;</content:encoded></item><item><title><![CDATA[Styled Components and Storybooks]]></title><description><![CDATA[I recently discovered two new react development tools that have changed how I approach React component development: Storybook and styled…]]></description><link>http://katieleonard.ca/blog/2018/2018-03-02-styled-components-and-storybooks/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2018/2018-03-02-styled-components-and-storybooks/</guid><pubDate>Fri, 02 Mar 2018 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I recently discovered two new react development tools that have changed how I approach React component development: &lt;a href=&quot;https://storybook.js.org/basics/introduction/&quot;&gt;Storybook&lt;/a&gt; and &lt;a href=&quot;https://www.styled-components.com/docs/basics#getting-started&quot;&gt;styled-components&lt;/a&gt;. &lt;!--more--&gt;I can quickly prototype a component with its data requirements, styles, and behaviour in one file, and in isolation from the rest of my application. This rapid prototyping has greatly increased my development cycle time, as I spend more time in code and less time flipping between the browser window, the browser console, css files, jsx files, and my terminal.&lt;/p&gt;
&lt;p&gt;Using these libraries has also had the pleasant side-effect of helping me design more pure components: instead of using whatever context is available in my giant application, I think about my component interface with real encapsulation in mind.&lt;/p&gt;
&lt;h3&gt;Storybook&lt;/h3&gt;
&lt;p&gt;Storybook creates a hot-reloading development sandbox outside of your running application, where you can create components free from global app dependencies. Building a component outside of your application context makes you think about what props are really needed to render a component. Is one component actually two components? What is the least amount of information your component needs to be a single atom.&lt;/p&gt;
&lt;p&gt;Writing a story for storybook is like writing a spec: you describe the features of the component variant (“with long title”), and provide a callback that renders your component with props that you specify.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token function&quot;&gt;storiesOf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Playbill&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; module&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;basic&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Playbill
      onClick&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;navigate to playbill&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
      title&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;foo&quot;&lt;/span&gt;
      imageUrl&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;https://virtualplaybill.s3.amazonaws.com/1517893742975_Magellanica&quot;&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;with long title&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Playbill
      onClick&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;navigate to playbill&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
      title&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;we are proud to present a presentation&quot;&lt;/span&gt;
      imageUrl&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;https://virtualplaybill.s3.amazonaws.com/1517893742975_Magellanica&quot;&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;You can interact with your components and see the consequences of those interactions in the action pane below.&lt;/p&gt;
&lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/90f72a5fb8f3c014967b271f66a380fd/2c288/styled-components.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 90.50632911392405%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAASCAIAAADUsmlHAAAACXBIWXMAAAsTAAALEwEAmpwYAAAC9klEQVQ4y4WSSWgUQRSGO0IOCgbFixIiihJF43JRgyASBRE0igtG0Ys4Qi6CBxXBBUVBMeJycEEUHXE5KKIhrqgRoobIZEJmSDIzOj3RmJ7pZXpS1V3VVd1VXdKTGAya+B8ePIrvvf9/lKTrummamqYpipKRM4qiqKqqabqmEd1wNc3RdaKpxDA8TXNVNZ/LZYN3TcvlcpJVlKqqiqJoqmpZMG+YppmF8D6Ed/L5sGnegTAMQBiAWwilKeWEOJRSQkgAO07QYIwJIa5LCfUhTAox3tCljy0lra1SR4eUzY0TQiLkoQjkFauQMHYAABBC13U9z6OUep6wrD7Hqfv5c1MstjkarY22b8lmtyK0HqHPQgjf50MwQigejydTKee3CCEAQDOPEPLAgJ2Rf9g2HiigQoEg5BRhMbwZJxKJvh99hBC7KNd15UxmwdKlUyZPqqiomDZ16sxZlXOrFpaNn9DU2CiEYIwNwYQQOZ2WZdkwDMuyAADUdbtjsYXbd8xes0aSJKlE2nmq/tCLqwu2rX394f0IeNAqKooQgjEWQvR0dU2vmr/nybNd507uvb6vof3AqXehS1+OfTfTIzL/GXVwCuf8azpdKknloX3bo/GNz5+su3e99sbpUPhQor9bCMH/hoctcM6TyeTEsrLVly5sefpy97UHtUcvbDxzcf/TK7Ih/wcWQnS2t6/aVnclLW9+/GrxwbPlNRsW7QotOXu87VtPAPMx4Vhn57Lly5tT8v1Y4lxTc8PDpvPhR4cv346nipu5P5btVCpVWlo6Z978FTWrT1y+2iz3P4p0NkZi/bpRPNgoMMaYMdbb21tdXT2nsnLmjBkra2qetUVedqefd6UUAMaCh0UpdV2XMYYRwtj5AnravnZ0RKKqpvq+73keY0wajQwiYARtKIR4m48cUW6euNtQH6p/8+6tEGJw7r/h4KsO2HYB2QM2gyxmJFt6P3nAIgWTQsg8b1TbGGNKKee+z3yf+9zjQUg/uLJgjDM2nPkXwnmKOOnxi1YAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;styled components&quot; title=&quot;styled components&quot; src=&quot;/static/90f72a5fb8f3c014967b271f66a380fd/f058b/styled-components.png&quot; srcset=&quot;/static/90f72a5fb8f3c014967b271f66a380fd/c26ae/styled-components.png 158w,
/static/90f72a5fb8f3c014967b271f66a380fd/6bdcf/styled-components.png 315w,
/static/90f72a5fb8f3c014967b271f66a380fd/f058b/styled-components.png 630w,
/static/90f72a5fb8f3c014967b271f66a380fd/2c288/styled-components.png 684w&quot; sizes=&quot;(max-width: 630px) 100vw, 630px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
&lt;h3&gt;Styled-components&lt;/h3&gt;
&lt;p&gt;Styled-components remove the disconnect between styles and components (they are literally connected with a hyphen 😄). Before styled-components, there were clear sides to the Great CSS debate: why do we even need CSS if we inline component styles? Is it just for performance? Why not use the React render cycle to handle dynamic styles?&lt;/p&gt;
&lt;p&gt;I am coming pretty late to the party here, but as a solid supporter of CSS over inline styles, styled components have completely won me over. Instead of filling your markup with &lt;code class=&quot;language-text&quot;&gt;style={{}}&lt;/code&gt; attributes, you create a new component that expresses the styles you specify.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; styled &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;styled-components&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; PlaybillContainer &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; styled&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;div&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;
  height: 415px;
  width: 250px;
  border: 1px solid black;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;Playbill&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;PlaybillContainer &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Under the hood, styled-components will generate a stylesheet and inject it into the head of your page:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;html&quot;&gt;&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;style&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;text/css&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;data-styled-components&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;fAjaVQ cjXYkN ktobWA bNUGoX fSQmFU sPlKa jPyvbr cDsQtG ddUpJT buzCko llbHNh wUSUC eapGFo gcivQF llqivM cHJMlW&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;data-styled-components-is-local&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;true&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;nonce&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;undefined&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token style&quot;&gt;&lt;span class=&quot;token language-css&quot;&gt;
...
&lt;span class=&quot;token comment&quot;&gt;/* sc-component-id: sc-fjdhpX */&lt;/span&gt;
&lt;span class=&quot;token selector&quot;&gt;.sc-fjdhpX&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token selector&quot;&gt;.cHJMlW&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;block&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;height&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;300px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;250px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;style&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Styled-components have effectively put an end to the styles-in-Javascript debate. They are an expressive way to have the best of both worlds: inline styles and cascading style sheets.&lt;/p&gt;
&lt;h3&gt;Quick start with both Storybook and styled-components&lt;/h3&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# install create-react-app&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# for babel boilerplate&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;npm&lt;/span&gt; i -g create-react-app
&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; create-react-app storybook-test-app
&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token builtin class-name&quot;&gt;cd&lt;/span&gt; storybook-test-app
&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;npm&lt;/span&gt; i

&lt;span class=&quot;token comment&quot;&gt;# install storybook and styled-components&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;npm&lt;/span&gt; i -g @storybook/cli
&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; getstorybook
&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;npm&lt;/span&gt; i styled-components
&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;npm&lt;/span&gt; run storybook

&lt;span class=&quot;token comment&quot;&gt;# open your new storybook at&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# http://localhost:9009/&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Your stories are saved in &lt;code class=&quot;language-text&quot;&gt;src/stories&lt;/code&gt;, and you can import them from an adjacent components folder for both quick development, and quick incorporation into your application.&lt;/p&gt;
&lt;h3&gt;Example&lt;/h3&gt;
&lt;p&gt;I am doing a React rebuild of my side project Virtual-Playbill, and storybook is the perfect place to play around with tweaks to the UI.&lt;/p&gt;
&lt;h4&gt;My component&lt;/h4&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; React &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;react&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; styled &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;styled-components&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; PlaybillContainer &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; styled&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;div&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;
  height: 415px;
  width: 250px;
  border: 1px solid black;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; PlaybillHeader &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; styled&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;div&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;
  padding: 10px 0 10px 0;
  font-size: x-large;
  max-height: 2em;
  text-align: center;
  width: 100%;
  background-color: yellow;
  border-bottom: 1.5px solid black;
  text-transform: uppercase;
  font-weight: bold;
  letter-spacing: 2.5px;
&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; PlaybillTitle &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; styled&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;div&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;
  text-align: center;
  font-weight: bold;
  font-size: large;
  max-width: 95%;
&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; PlaybillImage &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; styled&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;img&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;
  display: block;
  height: 300px;
  width: 250px;
&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;Playbill&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; title&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; imageUrl&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; onClick &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;PlaybillContainer onClick&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;onClick&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
      &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;PlaybillHeader&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;Virtual Playbill&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;PlaybillHeader&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
      &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;PlaybillTitle&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;title&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;PlaybillTitle&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
      &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;PlaybillImage src&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;imageUrl&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;PlaybillContainer&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;default&lt;/span&gt; Playbill&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h4&gt;My stories&lt;/h4&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; React &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;react&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; storiesOf &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;@storybook/react&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; action &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;@storybook/addon-actions&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; Playbill &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../components/playbill&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token function&quot;&gt;storiesOf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Playbill&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; module&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;basic&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Playbill
      onClick&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;navigate to playbill&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
      title&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;foo&quot;&lt;/span&gt;
      imageUrl&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;https://virtualplaybill.s3.amazonaws.com/1517893742975_Magellanica&quot;&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;with long title&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Playbill
      onClick&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;navigate to playbill&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
      title&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;we are proud to present a presentation&quot;&lt;/span&gt;
      imageUrl&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;https://virtualplaybill.s3.amazonaws.com/1517893742975_Magellanica&quot;&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Between styled-components and storybook, I don’t need to leave my component file until the component is finished. Feedback cycles are tight, which means I can try out different variations quickly before dropping the component into my application.&lt;/p&gt;
&lt;p&gt;Awesome! 😎&lt;/p&gt;</content:encoded></item><item><title><![CDATA[decorate your javascript]]></title><description><![CDATA[Javascript decorators are a form of metaprogramming: they add functionality to classes and properties. Unlike the GoF pattern, where…]]></description><link>http://katieleonard.ca/blog/2018/2018-02-28-decorate-your-javascript/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2018/2018-02-28-decorate-your-javascript/</guid><pubDate>Wed, 28 Feb 2018 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Javascript decorators are a form of metaprogramming: they add functionality to classes and properties. Unlike the &lt;a href=&quot;https://en.wikipedia.org/wiki/Decorator_pattern&quot;&gt;GoF pattern&lt;/a&gt;, where decorators modify instances of a class, Javascript decorators are run when the class, method, or property is installed, modifying all instances.&lt;/p&gt;
&lt;p&gt;Decorators are useful for adding extra functionality to behaviours and properties that would otherwise look like boilerplate — such as cacheing, access control, logging, or instrumentation.&lt;!--more--&gt;&lt;/p&gt;
&lt;h3&gt;How does it work?&lt;/h3&gt;
&lt;p&gt;A decorator function runs before the object it decorates is installed on the prototype. When you define an undecorated object like this:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ExampleWithoutDecoration&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;doWork&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;can\&apos;t you see I\&apos;m working here?&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The Javascript engine creates an object and installs the &lt;code class=&quot;language-text&quot;&gt;doWork&lt;/code&gt; method on its prototype:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;Object&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;defineProperty&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;ExampleWithoutDecoration&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;prototype&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;doWork&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; specifiedFunction&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;enumerable&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;configurable&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;writable&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;When you define a DECORATED method like this:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ExampleWithDecoration&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

  @DecoratingIsFun
  &lt;span class=&quot;token function&quot;&gt;doWork&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;can\&apos;t you see I\&apos;m working here?&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The Javascript engine saves some temporary state, runs the decorator function, and then installs the &lt;code class=&quot;language-text&quot;&gt;doWork&lt;/code&gt; method on the object’s prototype.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; methodDescription &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;method&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token function-variable function&quot;&gt;initializer&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; specifiedFunction&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;enumerable&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;configurable&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;writable&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

methodDescription &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;DecoratingIsFun&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;ExampleWithDecoration&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;prototype&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;doWork&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; methodDescription&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; methodDescription

&lt;span class=&quot;token function&quot;&gt;defineDecoratedProperty&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;ExampleWithDecoration&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;prototype&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;doWork&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; methodDescription&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;defineDecoratedProperty&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;target&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; initializer&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; enumerable&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; configurable&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; writable &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  Object&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;defineProperty&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;target&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;initializer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; enumerable&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; configurable&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; writable &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In this case, the &lt;code class=&quot;language-text&quot;&gt;DecoratingIsFun&lt;/code&gt; method is run with &lt;code class=&quot;language-text&quot;&gt;this&lt;/code&gt; set to the object prototype, and it has the opportunity to modify/return a methodDescription, or use the previously specified methodDescription.&lt;/p&gt;
&lt;p&gt;Consider &lt;code class=&quot;language-text&quot;&gt;DecoratingMakesSense&lt;/code&gt;, which makes the &lt;code class=&quot;language-text&quot;&gt;doWork&lt;/code&gt; method non-writeable:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;DecoratingMakesSense&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;object&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; methodName&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; description&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Decorating makes sense&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

  description&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;writable &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; description
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ExampleWithDetailedDecoration&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  @DecoratingMakesSense
  &lt;span class=&quot;token function&quot;&gt;doWork&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;can\&apos;t you see I\&apos;m working here?&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; makesSense &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ExampleWithDetailedDecoration&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
makesSense&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;doWork&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
makesSense&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function-variable function&quot;&gt;doWork&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;some other function&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;node&lt;/span&gt; build/main.js
Decorating makes sense
can&lt;span class=&quot;token string&quot;&gt;&apos;t you see I&apos;&lt;/span&gt;m working here?

/decorator-example/build/main.js:164
makesSense.doWork &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function-name function&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                  ^

TypeError: Cannot assign to &lt;span class=&quot;token builtin class-name&quot;&gt;read&lt;/span&gt; only property &lt;span class=&quot;token string&quot;&gt;&apos;doWork&apos;&lt;/span&gt; of object &lt;span class=&quot;token string&quot;&gt;&apos;#&amp;lt;ExampleWithDetailedDecoration&gt;&apos;&lt;/span&gt;
    at Object.defineProperty.value &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;/decorator-example/build/main.js:164:19&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;.&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;Getting started&lt;/h3&gt;
&lt;p&gt;Since decorators are currently in the &lt;a href=&quot;https://tc39.github.io/proposal-decorators/&quot;&gt;proposal stage&lt;/a&gt;, getting started requires a little tweaking of your standard babel/webpack/linter configs.&lt;/p&gt;
&lt;h4&gt;Babel&lt;/h4&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;&gt; npm install -g webpack
&gt; npm install --save-dev babel-core babel-loader babel-preset-es2015 babel-plugin-transform-decorators-legacy&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In your .babelrc&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;{
  &quot;presets&quot;: [
    &quot;es2015&quot;
  ],
  &quot;plugins&quot;: [
    &quot;transform-decorators-legacy&quot;
  ]
}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h4&gt;Webpack&lt;/h4&gt;
&lt;p&gt;Here is a barebones webpack.config.js example&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;var path = require(&apos;path&apos;)

module.exports = {
  entry: &apos;./index.js&apos;,
  output: {
    path: path.resolve(__dirname, &apos;build&apos;),
    filename: &apos;main.js&apos;
  },
  module: {
      loaders: [
    {
      test: /\.js$/,
      exclude: /node_modules/,
      loader: &apos;babel-loader&apos;,
      query: {
        cacheDirectory: true,
        plugins: [
          &apos;transform-decorators-legacy&apos;,
        ],
        presets: [&apos;es2015&apos;],
      },
    }
  ]
  },
  stats: {
    colors: true
  }
}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;(The important bit is to add ‘transform-decorators-legacy’ to the plugins array.)&lt;/p&gt;
&lt;h4&gt;Linting error — or is it? 🤔&lt;/h4&gt;
&lt;p&gt;If you use VSCode, you will probably run across a linter error that says&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;[js] Experimental support for decorators is a feature that is subject to
change in a future release. Set the &apos;experimentalDecorators&apos; option to
remove this warning.&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This is an error in the VSCode JS support, rather than a linter error.&lt;/p&gt;
&lt;p&gt;Add a jsconfig.json file to your project root with the following contents:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;{
  &quot;compilerOptions&quot;: {
    &quot;experimentalDecorators&quot;: true
  }
}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Be sure to restart VSCode, and the problem should go away. If it doesn’t, follow &lt;a href=&quot;https://github.com/Microsoft/vscode/issues/28097&quot;&gt;this thread&lt;/a&gt; for further information.&lt;/p&gt;
&lt;h3&gt;Build and run&lt;/h3&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;&gt; webpack
Hash: 63cf378bd6d165758ed8
Version: webpack 3.8.1
Time: 457ms
  Asset     Size  Chunks             Chunk Names
main.js  4.47 kB       0  [emitted]  main
   [0] ./index.js 1.7 kB {0} [built]
   [1] ./decorator.js 195 bytes {0} [built]

&gt; node build/main.js
Decorating is fun
can&apos;t you see I&apos;m working here?&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;For a detailed example checkout &lt;a href=&quot;https://github.com/keighty/decorator--example&quot;&gt;this repo&lt;/a&gt;. For more examples and a deep dive, checkout &lt;a href=&quot;https://github.com/wycats/javascript-decorators&quot;&gt;wycats’s decorator spec&lt;/a&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[least recently used (LRU) cache]]></title><description><![CDATA[I was recently challenged to implement a least recently used (LRU) cache in javascript, which taxed both my object-oriented javascripting…]]></description><link>http://katieleonard.ca/blog/2018/2018-02-23-least-recently-used/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2018/2018-02-23-least-recently-used/</guid><pubDate>Fri, 23 Feb 2018 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I was recently challenged to implement a least recently used (LRU) cache in javascript, which taxed both my object-oriented javascripting chops as well as my hazy memory of how to implement a linked list.&lt;!--more--&gt; An LRU cache discards least recently used items first (&lt;a href=&quot;https://en.wikipedia.org/wiki/Cache_replacement_policies#Least_Recently_Used_(LRU)&quot;&gt;wikipedia&lt;/a&gt;). Not only do you have to limit the size of the list, but you have to track when an item has been accessed recently and ensure it is not removed before an item that has been accessed less recently.&lt;/p&gt;
&lt;p&gt;Judging from the scores of implementations available from my first Google search, this appears to be a fairly common interview question. Here is the approach that I took:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Maintain performance by storing items in a hash map&lt;/li&gt;
&lt;li&gt;Use a queue-type linked list to keep track of access order: a new item is added to the end of the queue, while an existing item is removed from its place in the queue and re-added to the end of the queue.&lt;/li&gt;
&lt;li&gt;Keep the cache at the specified size by lopping off the head of the list (and removing those items from the map).&lt;/li&gt;
&lt;li&gt;Do it all using object oriented design principles.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;The API/object design&lt;/h3&gt;
&lt;p&gt;A simple cache should not have too many bells and whistles. It needs a &lt;code class=&quot;language-text&quot;&gt;get&lt;/code&gt; and a &lt;code class=&quot;language-text&quot;&gt;set&lt;/code&gt;, and possbily a &lt;code class=&quot;language-text&quot;&gt;size&lt;/code&gt; (useful for testing, probably not something most users desperately need). It should take a specific &lt;code class=&quot;language-text&quot;&gt;cacheSize&lt;/code&gt; as well, so we can set limits on the cache at startup.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;LRU&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;cacheSize&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_maxSize &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; cacheSize

  &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function-variable function&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function-variable function&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;key&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; value&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function-variable function&quot;&gt;size&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;The data structures&lt;/h3&gt;
&lt;p&gt;To access stored values in the cache in the most performant way, we store them with a key in a hash map:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// ...&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_map &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// ...&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In order to keep track of order access, we need to keep references to the head and the tail of the list, as well as an object to store the cached value and its place in the queue:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;//...&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_head &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_tail &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//...&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;Node&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;key&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; value&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;key &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; key&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;value &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; value&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;next &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;prev &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;The implementaton&lt;/h3&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;LRU&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;cacheSize&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_maxSize &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; cacheSize&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_map &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_head &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_tail &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function-variable function&quot;&gt;size&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_map&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;size&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function-variable function&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token parameter&quot;&gt;key&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; item &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_map&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;item&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;_dequeue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;item&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;_enqueue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;item&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; item&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;value&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function-variable function&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;key&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; value&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; node &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Node&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; value&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_map&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;has&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; existingNode &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_map&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;_dequeue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;existingNode&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;_enqueue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;node&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;_trimList&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; value&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function-variable function&quot;&gt;_trimList&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_map&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;size &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_maxSize&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;_dequeue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_head&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function-variable function&quot;&gt;_enqueue&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token parameter&quot;&gt;node&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_map&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;node&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; node&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_head&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_head &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; node&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_tail &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; node&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_tail&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;next &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; node&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      node&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;prev &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_tail&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      node&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;next &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_tail &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; node&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; node&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;value&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function-variable function&quot;&gt;_dequeue&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token parameter&quot;&gt;node&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_head &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; node&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; next&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; key &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_head&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;next&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_head &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; next&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_head&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;prev &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_head &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_tail &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; prev&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; next &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; node&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      prev&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;next &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; next&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      next&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;prev &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; prev&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_map&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;delete&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;node&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function-variable function&quot;&gt;toString&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; itr &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_map&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;entries&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; entries &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; item &lt;span class=&quot;token keyword&quot;&gt;of&lt;/span&gt; itr&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; node&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; item&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; value &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; node&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      entries&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;push&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; value&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; entries&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;Node&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;key&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; value&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;key &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; key&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;value &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; value&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

module&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;exports &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;LRU&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Checkout &lt;a href=&quot;https://github.com/keighty/lru-cache&quot;&gt;this repo&lt;/a&gt; for the full implementation and tests.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[writing test cases in java with enums]]></title><description><![CDATA[I recently discovered some new (to me) features of enums, and so naturally I am now using them for everything. One of these new-to-me…]]></description><link>http://katieleonard.ca/blog/2017/2017-03-18-writing-test-cases-with-enums/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2017/2017-03-18-writing-test-cases-with-enums/</guid><pubDate>Sat, 18 Mar 2017 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I recently discovered some new (to me) features of enums, and so naturally I am now using them for everything. One of these new-to-me features is using a constructor to give enum members properties and behaviour.&lt;!--more--&gt;&lt;/p&gt;
&lt;p&gt;For example, if I were making a list of colours, a simple enum would look like this:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;java&quot;&gt;&lt;pre class=&quot;language-java&quot;&gt;&lt;code class=&quot;language-java&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;enum&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Colors&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    RED&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    BLUE&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    YELLOW&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Everywhere in my code where I used to use the string &lt;code class=&quot;language-text&quot;&gt;&quot;red&quot;&lt;/code&gt;, I could replace with a less-spelling-error-prone-and-IDE-friendly &lt;code class=&quot;language-text&quot;&gt;Colors.RED&lt;/code&gt;. If I want to iterate over all the colors in my collection, I can use the &lt;code class=&quot;language-text&quot;&gt;values&lt;/code&gt; method:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;java&quot;&gt;&lt;pre class=&quot;language-java&quot;&gt;&lt;code class=&quot;language-java&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;loopColorEnum&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Color&lt;/span&gt; color &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;values&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token class-name&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;out&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;color&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// console output:&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// RED&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// BLUE&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// YELLOW&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;If I wanted to store the hex value for each colour, I can add a constructor and provide arguments for each member of the enum:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;java&quot;&gt;&lt;pre class=&quot;language-java&quot;&gt;&lt;code class=&quot;language-java&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;enum&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Color&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;RED&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;#FF0000&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;BLUE&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;#0000FF&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;YELLOW&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;#FFFF00&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;String&lt;/span&gt; hex&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token class-name&quot;&gt;Color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;String&lt;/span&gt; hexCode&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;hex &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; hexCode&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now I can access the hex property on all of my colours:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;java&quot;&gt;&lt;pre class=&quot;language-java&quot;&gt;&lt;code class=&quot;language-java&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;loopColorEnum&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Color&lt;/span&gt; color &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;values&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token class-name&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;out&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;color&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;hex&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// console output:&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// #FF0000&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// #0000FF&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// #FFFF00&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Finally, if I wanted to create a custom output for my enum that included the hex value, I can add a &lt;code class=&quot;language-text&quot;&gt;toString()&lt;/code&gt; function:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;java&quot;&gt;&lt;pre class=&quot;language-java&quot;&gt;&lt;code class=&quot;language-java&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;enum&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Color&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;RED&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;#FF0000&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;BLUE&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;#0000FF&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;YELLOW&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;#FFFF00&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token class-name&quot;&gt;String&lt;/span&gt; hex&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token class-name&quot;&gt;Color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;String&lt;/span&gt; hexCode&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;hex &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; hexCode&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;toString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Color: %s (Hex: %s)&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; hex&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;loopColorEnum&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Color&lt;/span&gt; color &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;values&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token class-name&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;out&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;color&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// console output:&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// Color: RED (Hex: #FF0000)&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// Color: BLUE (Hex: #0000FF)&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// Color: YELLOW (Hex: #FFFF00)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Pretty cool! Pair a constructor with the &lt;code class=&quot;language-text&quot;&gt;values()&lt;/code&gt; iterable, and you have yourself a handy-dandy test framework for repetitive but important tests. For example, I was re-visiting an old exercise from a data structures class and wanted to write a bunch of test cases without the repetitive boilerplate code for each one — so I built an enum:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;java&quot;&gt;&lt;pre class=&quot;language-java&quot;&gt;&lt;code class=&quot;language-java&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;CalculatorTest&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;InfixCalculator&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;enum&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Expression&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;ADDITION&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;1+2+3&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;SUBTRACTION&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;9-4&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;MULTIPLICATION&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;5*4*2&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;40&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;DIVISION&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;9/3&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;ADDITION_WITH_SPACES&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;5 + 7&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;12&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;MULTI_DIGITS&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;12 + 3 - 5&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;token keyword&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;String&lt;/span&gt; expression&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; result&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token class-name&quot;&gt;Expression&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;String&lt;/span&gt; expression&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; result&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;expression &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; expression&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; result&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token annotation punctuation&quot;&gt;@Test&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;test_solves_an_expression&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token class-name&quot;&gt;Calculator&lt;/span&gt; calc &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Calculator&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Expression&lt;/span&gt; exp &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Expression&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;values&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token function&quot;&gt;assertEquals&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;for expression &quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; exp&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;expression&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                    exp&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;result&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                    calc&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;calculate&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;exp&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;expression&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;When I create a new test case, I just add another member to the enum, and provide the string input and the expected result. Reducing the boilerplate made developing around edge cases far more wieldy, and I spent more time writing the actual code of the Calculator than I did creating tests.&lt;/p&gt;
&lt;p&gt;Adding a constructor, methods and properties to an enum makes it looks suspiciously like a class. In fact, that is how enums are implemented under the hood: they are classes with &lt;em&gt;benefits&lt;/em&gt;, such as:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;retrieve the constant value with &lt;code class=&quot;language-text&quot;&gt;valueOf&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;guaranteed singletons,&lt;/li&gt;
&lt;li&gt;clarity in switch statements, and&lt;/li&gt;
&lt;li&gt;built in ordering of members — an enum can act like an array, and return the order of a member the &lt;code class=&quot;language-text&quot;&gt;ordinal()&lt;/code&gt; method&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Sure, you could accomplish most of these using a class with &lt;code class=&quot;language-text&quot;&gt;public static final&lt;/code&gt; constants and a few hand-rolled methods, but you will impress your neighbours more with a well crafted enum.&lt;/p&gt;
&lt;p&gt;Awesome.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[iptables: middleware for network management]]></title><description><![CDATA[Some companies don’t allow their employees to use social media at work, and some countries don’t allow their citizens to access news outside…]]></description><link>http://katieleonard.ca/blog/2017/2017-02-25-iptables/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2017/2017-02-25-iptables/</guid><pubDate>Sat, 25 Feb 2017 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Some companies don’t allow their employees to use social media at work, and some countries don’t allow their citizens to access news outside of controlled outlets. How do these institutions control access to information that seems so available in other contexts? Through iptables. &lt;!-- more --&gt;&lt;/p&gt;
&lt;p&gt;When you enter facebook.com in the address bar of your browser (or open the native app on your phone), the information exchanged between your device  and the servers at Facebook is broken up into tagged chunks of data called packets. Iptables contain chains of rules, and each rule contains a policy for how to handle the network packets sent to and from your computer.&lt;/p&gt;
&lt;p&gt;For example, a company that wants to block incoming Facebook data can set up a custom rule that sends all packets from Facebook to the garbage instead of delivering them to the browser.&lt;/p&gt;
&lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/1b86e02d61d8bea18096e885ed065bbe/eafa0/iptables2.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 36.708860759493675%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAHCAIAAACHqfpvAAAACXBIWXMAAAsTAAALEwEAmpwYAAABZklEQVQY03WQS0vDUBCF8wPdu1FXCm7cKP4AH8WF1oWgIqgbH1RtERFFsWprV6YPIn0/UmuT2Ng0t22a29wmuXckrQguPDAzi5nDYT4OAAa2cx1JPvJ5MnABgDH47f9ptOX2AzsP8XKjqauom5FehXok8R5GpoIteHozwoLJF00AQNmUGrtTY/eW3hyaPXEn0wvHgaBNiCjl/bezK6HJ1aupdOUlmtTHfeVxn+gPfmqNOr809zwzllicEFN8x+xlTnGnYXHZG03kFQAoy+kzfuOC37yM7ypyNZzqrp1r6yEUFb70WqF04C9sL5cDezVJIoR8pLV2y+CIjV3mvUoZo14xy+rnRcF1Hdd1AGhVRpLaAaAOZZZhNHMZBkC9U8YBA/gh5A3qUhP3toLzVSU3RGNHBZQstIENHIBWpVQ8OsS27TpeHsf+YqWUYoxlWUZIBwaEEKQ3NU0lZEAp7RqG2tL7uD9yfQNO53R8gdlsFAAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;iptables2&quot; title=&quot;iptables2&quot; src=&quot;/static/1b86e02d61d8bea18096e885ed065bbe/f058b/iptables2.png&quot; srcset=&quot;/static/1b86e02d61d8bea18096e885ed065bbe/c26ae/iptables2.png 158w,
/static/1b86e02d61d8bea18096e885ed065bbe/6bdcf/iptables2.png 315w,
/static/1b86e02d61d8bea18096e885ed065bbe/f058b/iptables2.png 630w,
/static/1b86e02d61d8bea18096e885ed065bbe/eafa0/iptables2.png 939w&quot; sizes=&quot;(max-width: 630px) 100vw, 630px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
&lt;p&gt;If a packet fails to match any of the policy rules in the chain, it is usually dropped by default.&lt;/p&gt;
&lt;p&gt;Iptables are useful in many scenarios:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;to build your own firewalls,&lt;/li&gt;
&lt;li&gt;to restrict access to specific sites (like Facebook),&lt;/li&gt;
&lt;li&gt;to load balance incoming web traffic,&lt;/li&gt;
&lt;li&gt;to block a DoS attack, or&lt;/li&gt;
&lt;li&gt;to simulate a network or service failure in order to test the resilience of your system (my team uses this strategy for some game-day activities)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Administrator privileges are required, but you can use &lt;code class=&quot;language-text&quot;&gt;iptables&lt;/code&gt; on linux or &lt;code class=&quot;language-text&quot;&gt;pfctl&lt;/code&gt; on mac to in order to inspect or change any of your iptable rules.&lt;/p&gt;
&lt;p&gt;While I am neither a system administrator, nor particularly interested in bespoke network management, I do occasionally install software that will help me focus by blocking my access to distracting sites — it is always good to know some of the magic going on under the hood.&lt;/p&gt;
&lt;h3&gt;Resources&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;for Linux: &lt;a href=&quot;https://www.linode.com/docs/security/firewalls/control-network-traffic-with-iptables&quot;&gt;control your network traffic&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;for Mac: &lt;a href=&quot;https://pleiades.ucsc.edu/hyades/PF_on_Mac_OS_X&quot;&gt;how to use pfctl&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;an &lt;a href=&quot;http://www.thegeekstuff.com/2011/06/iptables-rules-examples&quot;&gt;interesting primer&lt;/a&gt; on common iptable rules&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[thread safety]]></title><description><![CDATA[While wading into the wide world of high throughput production Java, I have been enjoying guidance from “Java Concurrency in Practice” by…]]></description><link>http://katieleonard.ca/blog/2017/2017-02-04-thread-safety/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2017/2017-02-04-thread-safety/</guid><pubDate>Sat, 04 Feb 2017 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;While wading into the wide world of high throughput production Java, I have been enjoying guidance from “Java Concurrency in Practice” by Brian Goetz, as well as my friend and coworker, David Copeland. In a recent talk, David boiled down the range of concurrency problems to three main issues: atomicity, visibility, and ordering conflicts.&lt;!--more--&gt;&lt;/p&gt;
&lt;h3&gt;Atomicity&lt;/h3&gt;
&lt;p&gt;An atomic operation is one that executes in a single operation. A variable assignment (&lt;code class=&quot;language-text&quot;&gt;int x = 2;&lt;/code&gt;) is an example of an atomic operation (mostly* — see footnote). Incrementing a variable, on the other hand, is NOT an atomic operation.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;java&quot;&gt;&lt;pre class=&quot;language-java&quot;&gt;&lt;code class=&quot;language-java&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;NonAtomicCounter&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; count &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getCount&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; count&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;doWork&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; count&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;While &lt;code class=&quot;language-text&quot;&gt;count++&lt;/code&gt; &lt;em&gt;appears&lt;/em&gt; to be a single action it is actually three:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;read count,&lt;/li&gt;
&lt;li&gt;modify count, and&lt;/li&gt;
&lt;li&gt;write count.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If ThreadA and ThreadB share a NonAtomicCounter and both call &lt;code class=&quot;language-text&quot;&gt;doWork()&lt;/code&gt;, ThreadA can read the value of count while ThreadB is modifying it, making &lt;code class=&quot;language-text&quot;&gt;count&lt;/code&gt; vulnerable to lost updates.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Be suspicious of any shared state that is involved in &lt;em&gt;read-modify-write&lt;/em&gt; or &lt;em&gt;test-then-act&lt;/em&gt; sequences of actions.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;Visibility&lt;/h3&gt;
&lt;p&gt;Once a thread has read a value, there is no guarantee that it will ever check to see if another thread has modified that value.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;java&quot;&gt;&lt;pre class=&quot;language-java&quot;&gt;&lt;code class=&quot;language-java&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Main&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;boolean&lt;/span&gt; stop&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; args&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;throws&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;InterruptedException&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

        &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Thread&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt; stop&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;token class-name&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;out&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;still working&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;start&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Thread&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; stop &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;start&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Each thread can cache a local copy of &lt;code class=&quot;language-text&quot;&gt;stop&lt;/code&gt;, which means they will read the value once and then never check to see if it has been changed.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Be suspicious of loops that are gated by a variable that is visible to other threads.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;Ordering&lt;/h3&gt;
&lt;p&gt;The JVM has a just-in-time compiler that optimizes execution at runtime. The memory model guarantees deterministic behaviour &lt;em&gt;within&lt;/em&gt; a thread, but makes no promises about how instructions are ordered in the meantime.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;java&quot;&gt;&lt;pre class=&quot;language-java&quot;&gt;&lt;code class=&quot;language-java&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Main&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; args&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;throws&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;InterruptedException&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

        &lt;span class=&quot;token class-name&quot;&gt;Thread&lt;/span&gt; t1 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Thread&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; localA &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token class-name&quot;&gt;B&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token class-name&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;out&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;local A: &quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; localA&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;token class-name&quot;&gt;Thread&lt;/span&gt; t2 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Thread&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; localB &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token class-name&quot;&gt;A&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token class-name&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;out&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;local B: &quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; localB&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        t1&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;start&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        t2&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;start&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;/* POSSIBLE LOCAL VALUES
* localA: 0, localB: 0
* -------------
* localA: 0, localB: 1
* --------------
* localA: 2, localB: 1 =&gt; THIS SHOULD BE IMPOSSIBLE, RIGHT?
* --------------
* localA: 2, localB: 0 =&gt; WAT?
*/&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;How is it possible that t1 sees that A = 2? From &lt;a href=&quot;https://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html#jls-17.4&quot;&gt;the docs&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“The semantics of the Java programming language allow compilers and microprocessors to perform optimizations that can interact with incorrectly synchronized code in ways that can produce behaviors that seem paradoxical.&quot;&quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;What this means, is that even though the instructions are written in such a way that localA should not be able to see the reassignment of A, the compiler can reorder instructions to optimize evaluation. As long as the result of the computation is deterministic &lt;strong&gt;within&lt;/strong&gt; a thread, the compiler is free to change the execution order, inline assignments, simplify algebra, etc.&lt;/p&gt;
&lt;p&gt;In the above example,&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;java&quot;&gt;&lt;pre class=&quot;language-java&quot;&gt;&lt;code class=&quot;language-java&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; localB &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token class-name&quot;&gt;A&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;is the same as&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;java&quot;&gt;&lt;pre class=&quot;language-java&quot;&gt;&lt;code class=&quot;language-java&quot;&gt;&lt;span class=&quot;token class-name&quot;&gt;A&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; localB &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;When the instructions for thread1 and thread2 are interleaved, thread1 will occasionally see &lt;code class=&quot;language-text&quot;&gt;A = 2&lt;/code&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Be suspicious of operations involving multiple variables and ordering requirements.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;Thread Safety Analysis Guidelines&lt;/h3&gt;
&lt;p&gt;If you are dealing with a thread safety issue, ask these three questions:&lt;/p&gt;
&lt;ol start=&quot;3&quot;&gt;
&lt;li&gt;Do your threads share mutable state? Look for public getters and setters, or methods that return references to state rather than copies or primitive values.&lt;/li&gt;
&lt;li&gt;Do your threads share multi-variable states (invariants)? Can one component  change independently from others when they should always be treated as a single unit?&lt;/li&gt;
&lt;li&gt;For any publicly mutable state, is it an atomicity, visibility, or ordering issue?&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Solutions for thread safety issues&lt;/h3&gt;
&lt;p&gt;The Java language has a few solutions to offer:&lt;/p&gt;
&lt;h4&gt;The &lt;code class=&quot;language-text&quot;&gt;volatile&lt;/code&gt; keyword&lt;/h4&gt;
&lt;p&gt;Adding the keyword &lt;code class=&quot;language-text&quot;&gt;volatile&lt;/code&gt; to a variable declaration tells the JVM not to use a cached value for any read operations. This keyword will ensure that writes to a variable are always visible to other threads, but will not fix atomicity or ordering issues.&lt;/p&gt;
&lt;h4&gt;The &lt;code class=&quot;language-text&quot;&gt;synchronized&lt;/code&gt; keyword&lt;/h4&gt;
&lt;p&gt;Using a &lt;code class=&quot;language-text&quot;&gt;synchronized&lt;/code&gt; lock around a variable will address all three issues, at the cost of concurrency. If only one thread at a time can access your data, your program is single threaded. Common lock-gotchas include locking writes but not reads!&lt;/p&gt;
&lt;h4&gt;The &lt;code class=&quot;language-text&quot;&gt;final&lt;/code&gt; keyword&lt;/h4&gt;
&lt;p&gt;Making variables &lt;code class=&quot;language-text&quot;&gt;final&lt;/code&gt; addresses all three issues, but requires your state to be immutable. This approach is most useful in composition with other techniques.&lt;/p&gt;
&lt;h4&gt;Use guava libraries&lt;/h4&gt;
&lt;p&gt;Google has published a library of thread-safe collections that handle concurrent access for you. ConcurrentHashMap is one of my favourites, and you can check out the &lt;a href=&quot;https://github.com/google/guava/wiki&quot;&gt;user guide&lt;/a&gt; for more.&lt;/p&gt;
&lt;hr /&gt;
&lt;h4&gt;Note&lt;/h4&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;A variable’s declaration and assignment are really two operations: the allocation of memory to hold the value, and the writing of that value into memory. If a variable is declared and assigned within an object constructor, the object will not be published without variable initialization. However, if it is declared and assigned anywhere else, there are no such guarantees. For the purpose of this example, I am completely ignoring these implications :D&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;</content:encoded></item><item><title><![CDATA[effectively final]]></title><description><![CDATA[I have been working on a Java concurrency bug at work for the last few weeks, and the intertwining concepts of immutability and publication…]]></description><link>http://katieleonard.ca/blog/2017/2017-01-11-effectively-final/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2017/2017-01-11-effectively-final/</guid><pubDate>Wed, 11 Jan 2017 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I have been working on a Java concurrency bug at work for the last few weeks, and the intertwining concepts of immutability and publication have recurred several times. With the help of &lt;a href=&quot;https://www.amazon.com/Java-Concurrency-Practice-Brian-Goetz/dp/0321349601&quot;&gt;“Java Concurrency in Practice,” by Brian Goetz&lt;/a&gt;, I am starting to make sense of these concepts, and why these kinds of bugs can be difficult to reproduce.&lt;!--more--&gt;&lt;/p&gt;
&lt;h3&gt;What does it mean to publish an object?&lt;/h3&gt;
&lt;p&gt;“Publishing an object means making it available to code outside of its current scope, such as by storing a reference to it where other code can find it, returning it from a nonprivate method, or passing it to a method in another class.” (Goetz et al.)&lt;/p&gt;
&lt;p&gt;An object that is published is available for use outside of its declared context. Publication can be direct or indirect. Storing a reference to an object in a public static field, directly publishes that object to any client of the class.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;java&quot;&gt;&lt;pre class=&quot;language-java&quot;&gt;&lt;code class=&quot;language-java&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;PublishedObject&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; args&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token class-name&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;out&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;DirectlyPublishedObject&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;stringArray&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;token class-name&quot;&gt;DirectlyPublishedObject&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;stringArray&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;changed&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;token class-name&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;out&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;DirectlyPublishedObject&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;stringArray&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;DirectlyPublishedObject&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; stringArray &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;gotcha&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;/*
* Console output:
* gotcha
* changed
*/&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;DirectlyPublishedObject.stringArray&lt;/code&gt; can be retrieved and modified by any client that has access to the class (in this case, &lt;code class=&quot;language-text&quot;&gt;PublishedObject#main&lt;/code&gt; is the client). An object can also be indirectly published if it is a visible member of another object that is published:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;java&quot;&gt;&lt;pre class=&quot;language-java&quot;&gt;&lt;code class=&quot;language-java&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;PublishedObject&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; args&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token class-name&quot;&gt;IndirectlyPublishedObject&lt;/span&gt; ipo &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;IndirectlyPublishedObject&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token class-name&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; myPersonalStringArray &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; ipo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getStringArray&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;token class-name&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;out&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;myPersonalStringArray&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        myPersonalStringArray&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;changed again&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token class-name&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;out&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;myPersonalStringArray&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;IndirectlyPublishedObject&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; stringArray &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;gotcha&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getStringArray&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; stringArray&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;/*
* Console output:
* gotcha
* changed again
*/&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;If ObjectA obtains a reference to ObjectB, it doesn’t matter if ObjectB is declared private, it has now been publicly published.&lt;/p&gt;
&lt;p&gt;Why does publication matter? Shared objects have different publication requirements depending on whether they are mutable. From Goetz:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;“Immutable objects can be published through any mechanism;&lt;/li&gt;
&lt;li&gt;Effectively immutable objects must be safely published;&lt;/li&gt;
&lt;li&gt;Mutable objects must be safely published, and must be either thread safe or guarded by a lock.”&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;What does it mean to for an object to be immutable?&lt;/h3&gt;
&lt;p&gt;An immutable object must satisfy these criteria:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The class is not extensible (no methods can be overridden)&lt;/li&gt;
&lt;li&gt;All fields are marked final&lt;/li&gt;
&lt;li&gt;All fields are assigned in the constructor&lt;/li&gt;
&lt;li&gt;No internal state is modifiable by the client of the class (ie: no setters)&lt;/li&gt;
&lt;li&gt;No fields that reference mutable objects are made available to clients of the class&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;java&quot;&gt;&lt;pre class=&quot;language-java&quot;&gt;&lt;code class=&quot;language-java&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ImmutableObject&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;String&lt;/span&gt; name&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ImmutableObject&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;String&lt;/span&gt; name&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; name&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;IllegalArgumentException&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Must supply a valid name.&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; name&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; name&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; args&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token class-name&quot;&gt;ImmutableObject&lt;/span&gt; io &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ImmutableObject&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;keighty&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token class-name&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;out&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;name = &quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; io&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The ImmutableObject will not have any state other than a single field &lt;code class=&quot;language-text&quot;&gt;name&lt;/code&gt; that is initialized to the String value passed to its constructor. Because &lt;code class=&quot;language-text&quot;&gt;name&lt;/code&gt; is marked &lt;code class=&quot;language-text&quot;&gt;final&lt;/code&gt; and initialized in the constructor, there is no danger of encountering an instance of ImmutableObject in the wild whose name is not initialized.&lt;/p&gt;
&lt;p&gt;If an object violates &lt;em&gt;some&lt;/em&gt; of the requirements for immutability, but its state will never be modified after publication, it will still be treated as immutable by the compiler and JVM — it is &lt;strong&gt;effectively immutable&lt;/strong&gt;.&lt;/p&gt;
&lt;h3&gt;The String class is “effectively immutable”&lt;/h3&gt;
&lt;p&gt;In Java, an instance of the String class is not technically immutable, even though Strings are constant and cannot be modified after creation. They have another property (a private hash) that is lazy loaded only as it is needed:&lt;/p&gt;
&lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/a84bdf3b7455ed95ba1121b4ebf2a904/8c557/string_constructor.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 92.40506329113923%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAASCAIAAADUsmlHAAAACXBIWXMAAAsTAAALEwEAmpwYAAACpklEQVQ4y22SzWsTQRjG89+KCB6kUcT2VBVBREShNw+KBfFiFfXgWdBepGqTNJu02c1udr52vnYzs+/sl2Q3tI32N+9hGOaZeZ95pte0VHXVNM1Xdfhi9u72o+2du9tb/f7Bh4OmaZxzVVU1V9HLtAbIVWYgbfbGH9/Pvnljb+ydzP2509Btqje5EPujIcM4zcxwQo5+4tMJDSNEIuSj+ev5l/3hp2d7zw9/HFprOeeUUmPMhTgYjSjGzjkpTRgn8wWLieaJm1H0NHr7xvu8+/jB0c+jlbX/mu+FE48RAgBSWUQUFzaNfTh6KUMv8IJZ5HdtN815XRLPT0YMY3BOp5YyTZMsXsT1n1fHn55cu37j4e7D4Gwu03yOTMxyzIvMVOdH9ILRkGIMAIiK8WwRY4WooShOUIAQxpikMpOJ4Qkk1CYst3l52XMrdi5bgh/yMMKLBQ0XJMbCWOMcOHB5Bs4CLAEM1HV12fOk81yVpYPcOShcC4C1NtUpANjcAuTgAABMS/d4a8/tZkcJS1o4F4wyISXGhItVC7bFmNWkLMsu7Z4/GHSeSaIZV1mm9TIT0lpt0zQnbMnlsiyLq39Y6I3jKLJ5HiI+DRaMMEZXg2CiVdp0+dT11eLI8yjGOUBRVN5pEngIx/hsduZ7oaC6af6JdlMcDAdsLS42btjU1HVd1VVV11VL98l7wXAdFThHKZVSKqUQQpQyzoVSSrQkCU9VKlcLyjm3vhlNfuskLJ0qQCoeK4EyTZSItUSpwloiLZAUcSrwFI2mwTGKJgSdceqnirRREQwOisIpJbuqqvK8ivapJya8j17d23/Uv3mrf6e/tbW1s7PTCwaDOAxzyLk0QmZKKUKVEFIqwYTmTCulK1t8R79eegd+FEyn08nJqXcyxRT/BT6T5twLL1OXAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;string constructor&quot; title=&quot;string constructor&quot; src=&quot;/static/a84bdf3b7455ed95ba1121b4ebf2a904/f058b/string_constructor.png&quot; srcset=&quot;/static/a84bdf3b7455ed95ba1121b4ebf2a904/c26ae/string_constructor.png 158w,
/static/a84bdf3b7455ed95ba1121b4ebf2a904/6bdcf/string_constructor.png 315w,
/static/a84bdf3b7455ed95ba1121b4ebf2a904/f058b/string_constructor.png 630w,
/static/a84bdf3b7455ed95ba1121b4ebf2a904/8c557/string_constructor.png 700w&quot; sizes=&quot;(max-width: 630px) 100vw, 630px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
&lt;hr&gt;
&lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/4a17e323063074b89a84da69d8ac8ed6/374ac/string_lazy_hash.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 59.49367088607595%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAIAAADtbgqsAAAACXBIWXMAAAsTAAALEwEAmpwYAAABx0lEQVQoz01S2Y6jMBDk/z9nX/YL9mEfhoz2mI2USQIBMgE7gK/2gd29MiSjabUsH1VddrWLqiz7pjEAMUYxCzDgnQcDAOCcAwBjjLXWOee9t9aGEBCR1iiq3Y51nQEgoo51+2bfjm3N6klMzjoppdbae78sS4wxpYRrfJLLoWszGbEX/YmfjsPxfD9zzZ11IYSUkvfeGBNjRMSUEj2jqMpyaDMZEZlgFa/aj3YYhp71432cpmkcx+v1ejqdhBDzPEspAWArsSpv5JSUUkJKrbQUknO+QYUQeV+ITZyIvlw7G3Yxa7EN7YN3zjrnLaw+OWcBfIgrPhFhzszHon7dtecKLBjt93vWtFNXXS/nBizkB8aYMgwXxZapoelIwPOob2Tnx5v16vY8u6rq24rX7y17H7o3phWaeYj8X1Q9RUeizmRxyRPVra16GkaEQoR+kNOsZpE0v6nDj/vvn+KDu4jBKhoPZHoyAxlGmFbl9ZPQ2kALfp70ndv573f99o3XBwfkYcl9DpamAw1/MlPfyMvi/PLyIBP5EMZeqdEEJ9PtF6ZIXwNT1lRX8npbF1X5wq6tAYMYhTAD09bZTzTi095HPg422/8DU/uqGPuTOuwAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;string lazy hash&quot; title=&quot;string lazy hash&quot; src=&quot;/static/4a17e323063074b89a84da69d8ac8ed6/f058b/string_lazy_hash.png&quot; srcset=&quot;/static/4a17e323063074b89a84da69d8ac8ed6/c26ae/string_lazy_hash.png 158w,
/static/4a17e323063074b89a84da69d8ac8ed6/6bdcf/string_lazy_hash.png 315w,
/static/4a17e323063074b89a84da69d8ac8ed6/f058b/string_lazy_hash.png 630w,
/static/4a17e323063074b89a84da69d8ac8ed6/374ac/string_lazy_hash.png 634w&quot; sizes=&quot;(max-width: 630px) 100vw, 630px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
&lt;p&gt;A String is considered effectively immutable because its internal state is completely encapsulated and its external state isn’t changed after it has been published. Even though the hash field is not final, and is only assigned as it is required (a performance optimization), it is not modifiable by any client. The program can treat Strings as if they are immutable, even if they don’t strictly fit all of the criteria.&lt;/p&gt;
&lt;h3&gt;How can I make my objects effectively immutable?&lt;/h3&gt;
&lt;p&gt;By ensuring that the internal state is completely encapsulated, and any mutable internal objects returned by a public method are copies, not references, you too can enjoy the benefits of at-will publication.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;java&quot;&gt;&lt;pre class=&quot;language-java&quot;&gt;&lt;code class=&quot;language-java&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ImmutableObject&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;EffectivelyImmutableObject&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; stringArray &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;gotcha&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getStringArray&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;// return a COPY of the mutable object, not a reference&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Arrays&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;copyOf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;stringArray&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; stringArray&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; args&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token class-name&quot;&gt;EffectivelyImmutableObject&lt;/span&gt; eio &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;EffectivelyImmutableObject&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token class-name&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; myPersonalStringArray &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; eio&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getStringArray&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

      &lt;span class=&quot;token class-name&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;out&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;eio&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getStringArray&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

      myPersonalStringArray&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;changed a copy only&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

      &lt;span class=&quot;token class-name&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;out&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;myPersonalStringArray&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token class-name&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;out&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;eio&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getStringArray&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;/*
* Console output:
* gotcha
* changed a copy only
* gotcha
*/&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h4&gt;RESOURCES&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Peierls, Tim; Goetz, Brian; Bloch, Joshua; Bowbeer, Joseph; Lea, Doug; Holmes, David (2006-05-09). Java Concurrency in Practice. Pearson Education. Kindle Edition.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.oracle.com/javase/7/docs/api/java/lang/String.html&quot;&gt;javadoc for String&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[annotating java]]></title><description><![CDATA[Annotations are a means of adding metadata to Java source code. They can be applied to declarations of classes, fields, methods, and types…]]></description><link>http://katieleonard.ca/blog/2017/2017-01-08-annotating-java/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2017/2017-01-08-annotating-java/</guid><pubDate>Sun, 08 Jan 2017 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Annotations are a means of adding metadata to Java source code. They can be applied to declarations of classes, fields, methods, and types (as of Java8) in order to pass instructions to the compiler. Annotations can even be evaluated at Runtime.  &lt;!--more--&gt;For example, &lt;code class=&quot;language-text&quot;&gt;@Inject&lt;/code&gt; is an annotation from the Dagger dependency injection library used to indicate which constructor should be used to instantiate a class. &lt;code class=&quot;language-text&quot;&gt;@Inject&lt;/code&gt; also tells Dagger to create the dependencies identified in the constructor parameter list.&lt;/p&gt;
&lt;h4&gt;Provided by &lt;code class=&quot;language-text&quot;&gt;java.lang&lt;/code&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;@Deprecated&lt;/code&gt;: don’t use the marked object. This annotation should be accompanied by a comment explaining the reason and alternative.&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;@Override&lt;/code&gt;: this method overrides a superclass method.&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;@SuppressWarnings&lt;/code&gt;: the compiler will not report warnings generated by this method.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Create your own&lt;/h2&gt;
&lt;p&gt;Annotations can be used to replace verbose code comment templates, and since they are ostensibly interfaces, they can be created the same way you would any other interface.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;java&quot;&gt;&lt;pre class=&quot;language-java&quot;&gt;&lt;code class=&quot;language-java&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// src/CustomAnnotation.java&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token namespace&quot;&gt;java&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;lang&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;annotation&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Documented&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token annotation punctuation&quot;&gt;@Documented&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Annotation of an Annotation -- so meta! [1]&lt;/span&gt;
&lt;span class=&quot;token annotation punctuation&quot;&gt;@interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;CustomAnnotation&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// [2]&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// [3]&lt;/span&gt;
    &lt;span class=&quot;token class-name&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token class-name&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;author&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;default&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;[unknown]&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// [4]&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;CustomAnnotation&lt;/code&gt; has an annotation of its own! The &lt;code class=&quot;language-text&quot;&gt;@Documented&lt;/code&gt; annotation ensures that CustomAnnotation and its properties will be included in the Javadoc when it is generated.&lt;/li&gt;
&lt;li&gt;Declare a new annotation using &lt;code class=&quot;language-text&quot;&gt;@interface&lt;/code&gt; instead of &lt;code class=&quot;language-text&quot;&gt;interface&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Fields &lt;code class=&quot;language-text&quot;&gt;id&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;description&lt;/code&gt; are considered required because they are not given default values. Values for &lt;code class=&quot;language-text&quot;&gt;id&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;description&lt;/code&gt; must be provided when using &lt;code class=&quot;language-text&quot;&gt;@CustomAnnotation&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;author&lt;/code&gt; is an unrequired field because a default value will be used if one is not provided.&lt;/li&gt;
&lt;/ol&gt;
&lt;h4&gt;Annotations for Annotations&lt;/h4&gt;
&lt;p&gt;When defining an annotation, you can indicate how it should be used:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;@RetentionPolicy&lt;/code&gt;: How should the annotation be stored? Only in source, included in the generated Class, or passed all the way to the JVM for Runtime evaluation?&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;@Documented&lt;/code&gt;: Include the annotation when generating Javadocs (default is false).&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;@Target&lt;/code&gt;: A list of locations where the annotation can be used (constructor, field, method, etc).&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;@Inherited&lt;/code&gt;: The annotation properties can be inherited from the superclass.&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;@Repeatable&lt;/code&gt;: The annotation can be used more than once (declaring multiple authors, for example).&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Using your CustomAnnotation&lt;/h2&gt;
&lt;p&gt;Use &lt;code class=&quot;language-text&quot;&gt;@CustomAnnotation&lt;/code&gt; to decorate your code:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;java&quot;&gt;&lt;pre class=&quot;language-java&quot;&gt;&lt;code class=&quot;language-java&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// src/Main.java&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Main&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;

    &lt;span class=&quot;token annotation punctuation&quot;&gt;@CustomAnnotation&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;id &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; description &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Custom description&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;printSlogan&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token class-name&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;out&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;This method uses a @CustomAnnotation&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token annotation punctuation&quot;&gt;@CustomAnnotation&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;id &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; description &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Custom banner&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; author &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;keighty&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;printBanner&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token class-name&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;out&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;This is a printed banner for: &quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; message&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;When you generate the javadoc for Main.class, the annotations will be included in the method descriptions:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$  javadoc src/com/keighty/Main.java -d .&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 578px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/718494a4f1582a705b2a5c6e68f9aa78/508ef/javadoc_annotated.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 79.11392405063292%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAQCAIAAACZeshMAAAACXBIWXMAAAsTAAALEwEAmpwYAAACD0lEQVQoz42Sz27UMBDG85g8Aa/BnTsXJMSJMwgJceBeVCpaqQuooWw3u/mzSRzbY8f2jO0ki9Kt2i0rpH76aWR5ZGvmm0mqqlwsLtP06sfiEgCGGD1R8P4pJIyLdJmVdVds2bYVNZNPJ+k4pMtN0+mm01sGt6j9oWplzVR9dwk1U1UrD0m8JymFtUYK3pteKZBSCMENaNSWiw5AghSm11KK3WMl3nskIh+QCMkTeUcUKbZWZKaKPs5Z8uTnlA/hkKSq25Ozi5Nv59erMt/ydcU2VbcsmrebT6/zD6frtCjFTdGs8nZVtHM8ILEO2w4aJloOnVBMKgP4i2fPfr743H5VaL0f0AfykeYqwiFJCEH3VhurjTHW9caVVbtl3Z82B6UUAMwuSCkFgER002566BkROWfOGq2VlEIKUTd1XTcxxGmaYpgVYwi3/Y7j+MgwJG+s22MdWocOyeFs3sbWgD1RcLdeIvl96p6kqtnJ2cXp+eV1Vua1WFfduuqKUp6u0zf5x3erL+u8mw0r2pu9ZwckDolxYBz2hnGpGs53fveqeP88ffkdroY4+bnuIcR/SeIw+BDnCfvgQwwhbptOcHVVZ4vyt2JivzMAcpqmoyUhUgCEaKzpTQ8KljfZMtsoAZJxLniMcRiGcRiP3u4SItJaI6K1tjemn6UR3TiN91OZ/qNk/nUcH+Jwp3CkeKS/D9+GJ3QfJDcAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;javadoc annotated&quot; title=&quot;javadoc annotated&quot; src=&quot;/static/718494a4f1582a705b2a5c6e68f9aa78/508ef/javadoc_annotated.png&quot; srcset=&quot;/static/718494a4f1582a705b2a5c6e68f9aa78/c26ae/javadoc_annotated.png 158w,
/static/718494a4f1582a705b2a5c6e68f9aa78/6bdcf/javadoc_annotated.png 315w,
/static/718494a4f1582a705b2a5c6e68f9aa78/508ef/javadoc_annotated.png 578w&quot; sizes=&quot;(max-width: 578px) 100vw, 578px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
&lt;h2&gt;Annotating a field vs annotating a parameter&lt;/h2&gt;
&lt;p&gt;There are no hard rules about whether one should annotate a field or a constructor parameter, but which ever you choose you should use that pattern consistently.&lt;/p&gt;
&lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/eaf060e60f7c7027ea095804aeae254f/b5bda/nonnull_annotation.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 63.291139240506325%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAANCAIAAAAmMtkJAAAACXBIWXMAAAsTAAALEwEAmpwYAAAB+ElEQVQoz52SuW7UUBiF57V5Bh4EakRDBVUgmQShODNkxvF6vfvavvu+oAlIgICGT39xmk/nFP8OI5QkY/Y0ThOoymzdZu+1NVIIrrW2ProQfYjGxRAvwfpofPzODq5bXiCEGGcLxhPjkPGFMThNHaWkwjHf4sBijWNHLwHg2NMf/o6gocizh+NweBy3pfNOh+h9cDG6GHWL1XHU9aYnqstNlZvusO6JrjcVgtq9fuheXpU3t9mnz2AaJrJUVxl4kzQUwxgF1xIJhaTchFRGUCWYFlgKokTwfPcqWd4/4blncJF9z7+W5MWH6e0Zdd0EZ4gxEpqGEOLf2BXDwqU+nZbjsT7fJ4eHw7vbQ3o+tQ0AAEgpQ7yof95FlpTE4Kz1jCq2MsVUMJJh/K+235oxoVKK9PFjWSSgSev6kKYFnFcAqrZtCMEdqiqYgrUo4RnxLcYYnnmWMbbGDT3MMlA9TU3ZlEXewHKkzUDBwifIxg5VPQI9rlcG4y+DdoQQaxUhrRJQ6VWIlQullUMrwiu22hKFNg5XPgspCMHaqXarFjaH8CxLqZIv1/ub/f3d8f7u+m5/m1bnesxbCGpY5PMpn88DaSkl9WM7tjOWK1fsImOMnXOXv7PWGmeNd85pp6w3xmthmDJCW+WCDz5obpQwP2cjhLTW8b/4Bl9R3sVH39X4AAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;nonnull annotation&quot; title=&quot;nonnull annotation&quot; src=&quot;/static/eaf060e60f7c7027ea095804aeae254f/f058b/nonnull_annotation.png&quot; srcset=&quot;/static/eaf060e60f7c7027ea095804aeae254f/c26ae/nonnull_annotation.png 158w,
/static/eaf060e60f7c7027ea095804aeae254f/6bdcf/nonnull_annotation.png 315w,
/static/eaf060e60f7c7027ea095804aeae254f/f058b/nonnull_annotation.png 630w,
/static/eaf060e60f7c7027ea095804aeae254f/b5bda/nonnull_annotation.png 643w&quot; sizes=&quot;(max-width: 630px) 100vw, 630px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
&lt;p&gt;If you use the &lt;code class=&quot;language-text&quot;&gt;@Nonnull&lt;/code&gt; annotation in the constructor, the compiler will warn if there is any use of the constructor where the parameter could be null. If you use the &lt;code class=&quot;language-text&quot;&gt;@Nonnull&lt;/code&gt; annotation on the field, you will have to do your own null checking when assigning the field.&lt;/p&gt;
&lt;h4&gt;RESOURCES&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.oracle.com/javase/tutorial/java/annotations/index.html&quot;&gt;java tutorials&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://crunchify.com/understanding-java-annotation-annotation-examples/&quot;&gt;crunchify.com&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[Keighty's 2016 - by the numbers]]></title><description><![CDATA[Many people would like a do-over of 2016, but this was a pretty epic year for me. I was traveling pretty constantly, reading voraciously…]]></description><link>http://katieleonard.ca/blog/2016/2016-12-27-2016-year-in-review/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2016/2016-12-27-2016-year-in-review/</guid><pubDate>Tue, 27 Dec 2016 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Many people would like a do-over of 2016, but this was a pretty epic year for me. I was traveling pretty constantly, reading voraciously, and enjoying each left-turn my career has taken me. I started the year helping to build instrumentation for single-page applications, bounced into some UI projects using React, and spent the last quarter ensconced in a crash-course in Java Concurrency. &lt;!--more --&gt;Other highlights include achieving US Residency (so long for now, Canada 🇨🇦  ), seeing a more reasonable amount of theater, and shipping more diverse side-project code than ever. Check out my personal infographic (thanks &lt;a href=&quot;https://www.canva.com/&quot;&gt;canva.com&lt;/a&gt;!):&lt;/p&gt;
&lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/808e36f3b1fb8aaf9b29b8804fac0a7c/5a190/2016-year-in-review.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 250%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAyCAYAAABcfPsmAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAJIUlEQVRIx6WX+VNb1xXH9Zc1CQIM2EDAsR0nduI1TprVcdZf2ml/7Eynk5mmk8R27DhJ006bGGODtbMKSSBhzGILMPsmCQkwSELLu+fT3neF7WTcTmf6Zs6c713Oeedevfu9XzkARASllG36KZfLFItFRCmscpm9Obpt+yfmPxmn+x0azM8v4Pd10dvbTzAYIjoUY3TiPg9m54nHp+jp7SfQ1cPs3Dx9/SHu3h3D6/UzHLtDT3efHbu8vGIntROWSiXy+Ty7+V1y2Swly8JKJigmk5SLRbKbm+S2dygVi+S3tynk8+TyuxQKBTsul8vbOeyEusynPTJ5Hwn2ImN3IdgDQ2FkoBcCHliYe3qMWbI82pdH+wSoaAQV7keNRFE62UYGNTeD5enA6g3Yc34WZxdW2cNHb3jCS6mEFEuIArHUzyvZ+xGeUqWD9TDaJDOCrA9BKoRk7qDSw6j1sPG6nRhA1gdR6RFUKoxKRWys+/ZiSMdwEGhC/AcQfxMEmhF/I3Q3Qt/z0NsEvRXc1wxdjdDbbHBfo/E9lZhAI3Q14xBfHfjroGcf0r0PuurJtNUycaWKqW+d3LvqZPSyk/ErTrbaa5j53snEFd1XxfBXVaSv10KgHjuPr05X2IC49qMut6K+aQFfAw87G1lte4HEjRYW/tHMWlszK9db2OhoJX2zhcSNVpavH2Lhx4NsdzTaBYmvAfwNusIGrM8PUv7NUcq/O4p1uRn6D0P0LRh8A4bOQeQ0hE/C0DsQOWtw7B2IvgH9LyNdz9vJ8NXjkNv7sf54GOuzQ1h/Ooz1eQviP4pEfo0MvIaEXkf6X0WCpwzWfXvtgTPI4Hug+/cS4q9HfXmQ8m+PUv79UdTVJug7jITfQvpPIKHXkPCbBmsbOGsS976IdB80vucQ4t+P2Am7NDiA+q4V9fcW9AvoewkG9fJeh9BZCJ2D8DmInoeBMxD7AHoP2z+CPV9XF9gPgQM4pOM5pONZ8D2LuJ9Fbv0K8TUh3ceRwDGk5zjia0Y6qxF3HeKqQTprkU4nclvHVkzjzudwSOw7VOQqKnQRFb2GGryGCl9C6f7Y31Dhb1BDV8zYwEVUxMyzQl+jwheR2LeVmItI9CoO2TtCos9m5fwo/udHx9g5lMEOHa2URS6ftbOWy0XKVolkMkkykSCRSLCwMM/q6gqpVJJ0Os3y8jJLi4ukM2kMuahKFQqHZlvN0Pcm7ttEu7u7S2F3l8n4JGOjY8zMzDIcGyYWHWZ8/B6LCwvEolGbXOfn5vklW9lsMzc3z2R8yg5IpzNmLaUEWOmKX4fyGpQTUExAOQmyBdYWkluG4saj9TtKpTLT0w8YGRllfGyCpaVlewlqaxL18AFqe+6xbd5DtmdQO0uonUUktwpWAbF27RixGVspe4k2vedyWJaFWGXILiI780h2CSlsGJ9bRbZnjenxfMJ4nby0bRI+jWD/n8chmXVUMoHa2EA2N5BUAsmkUVsbqFQCtZ5CbW2i1pOoVBLReC9Gz9/MmJiNjD3mEPcZxHUCXKfBq/FJpPMUeM6C5yS4ThrsO2Ww6wz4TlfGzoDHxEvHKcR1Fge+GsqeWrI39pG9UYvy1aC8NWy0VZPtqCHdVkP6ejXrP1Wz2V7Dw3bTTmn7qZqdmzXgr0V8NeCt0QS7n5KnhtkLjaz+oQnp2UfZ3UD0q2qmv6sm9pVh7dBfDHPHr9Uw+EUVfX+uZuSSk/kfqsG/zyZYzTiOkruejPsV5js+YfGnY+TcTeDfD6FXYOAEhE9B5AyEK3jgOES0P2LaIc2Lp0GTrL4Ckm2NPIiPkUiluBPsYNn1lj0g4beRwfNI5B0k+hEq8q7BsU9Rg++b9tAFpO849BxB9AWn+XDX08SG+xg77iMUAkfNhaVvwsF3kcG3kaHzSN/LiO7ret6Qalcz0tWCdL+ABA5UeNFwogN3FXieMeZ6BnE7EY8T8dYh3nrEW2ParucQd8V+hqsex7ircCj/pyj3RyjvByj/JyjPxyjPBZTvAyz3h1iu8zZWvk+xXBewfNo+Qbk/RHk1/hhLx3veR/wf45BCEQpFJJuzPYUSZPNQMrqQYhmKJShbxjRWYsbzuwZryxeQXN4cPUspdnI5CsUiSoRCqcTM7AKx4REiQ8Pci0+xuLRCZChGeDBKKDzI/clpZuYWGByMEhwIs5pIPNaHW1tbrK6usbS0ZOs8ZZXZebhBJp0itbbE5kaa7a0NUolV1lMpEmurbGbW2Xm4yfp6msRawiaWR/owk8kQvx9nKj5FXi9DyrA9Cbk5KKxAMQm5BchOQikFhVUzlp3R6/ulPgS9W11fX2HE7TEDVhHZvI9o/tMUtbNg86BNWw+nH/utSWPlQuVeEl1hResVC0i5VNF/JdDkmV+DnObDDOQTsJtCdJ/GxU37ZXpc40olpkL5T6LzKe3/hs0eTgZQ4y7UuA812YVMaOyxsZpwY426UPEurHserNHbWPcCWHGfjdWEjglgjekYLzLVjUNu1iMd+5Bb2upszK190FEPrjpw1xnsrje4sw5cFdxRB7frwVNnx0h7RR/aGrG9Ebl1ALobKHrrGb/qZPaHGgKfVTF21Un4CyfRi9XELjkZvuRk7Eo103+tJXbRSeQLJ3n98u6KPlTfN6MutWJdbEX+2YTy72fT9RLbt1tZ/PEgmc6jrLUdJHXzEMn2F1hrf5FE+xEy7U2stB1i5XorZV9zRR+6G0yyL1tRl1tQl1rA2wBDr0PknBGcwxeMwNzjxuibph161cwbfs/W11oWO8RbkcOXtB1EXWsxIj7yJhI6VxGWrxnTuO8YEjxtdGLPYUNhmg/9FUms7xS9meqa1ogHkI5aW/NJ6A2TUAdqpRo8gQRPVvBpI0T1C7y1YNNdLXhrcUj/KxA8hvS+DP3HIXjcJlQGThmxqX3wlBGawROmrcWnPXba7rNz6Ji+YzjILZsvPjtvjlguYRTD1gMku4Jsz5tjl11GdpaQrWnTp9saZxcgnzR+Z/4Jfbj31a+soOJx1Ohd1INp1PQ0amoKNTeLGh9HTU6i7t5BTU0iqfVHmlIe/TWTPX0Hks+hhodQd4dR0TDqTtT8gdR+Oo4K9aNGh1EjMVQkiBq/iyjrsUb8Nzn8C86YdQ2smerrAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;2016 year in review&quot; title=&quot;2016 year in review&quot; src=&quot;/static/808e36f3b1fb8aaf9b29b8804fac0a7c/f058b/2016-year-in-review.png&quot; srcset=&quot;/static/808e36f3b1fb8aaf9b29b8804fac0a7c/c26ae/2016-year-in-review.png 158w,
/static/808e36f3b1fb8aaf9b29b8804fac0a7c/6bdcf/2016-year-in-review.png 315w,
/static/808e36f3b1fb8aaf9b29b8804fac0a7c/f058b/2016-year-in-review.png 630w,
/static/808e36f3b1fb8aaf9b29b8804fac0a7c/5a190/2016-year-in-review.png 800w&quot; sizes=&quot;(max-width: 630px) 100vw, 630px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;</content:encoded></item><item><title><![CDATA[browser-sync is the easiest webserver EVER]]></title><description><![CDATA[Browser-sync is the fastest way to spin up a local web server. It will even open your default browser with the entry point you specify, and…]]></description><link>http://katieleonard.ca/blog/2016/2016-10-23-browser-sync-webserver/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2016/2016-10-23-browser-sync-webserver/</guid><pubDate>Sun, 23 Oct 2016 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;https://www.browsersync.io/&quot;&gt;Browser-sync&lt;/a&gt; is the fastest way to spin up a local web server. It will even open your default browser with the entry point you specify, and live-reload your changes as you make them. It couldn’t possibly be any simpler to test out a site you’re developing locally.&lt;/p&gt;
&lt;!--more--&gt;
&lt;h2&gt;1. Install browser-sync&lt;/h2&gt;
&lt;p&gt;To get started, install the browser-sync package from npm:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ &lt;span class=&quot;token function&quot;&gt;npm&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; -g browser-sync&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;2. Configure the server&lt;/h2&gt;
&lt;p&gt;Setup a simple static project folder like this (&lt;a href=&quot;https://gist.github.com/keighty/9e5eb136c27b6a4f98f7c4f49d749256&quot;&gt;gist&lt;/a&gt;):&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;.&lt;/span&gt;
├── bs-config.js
├── foo
│   └── index.html
└── index.html&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In your bs-config.js file, list the configuration options for how browser-sync should serve your files, including which file extensions it should watch for changes (&lt;code class=&quot;language-text&quot;&gt;&quot;*html&quot;,&quot;*js&quot;,&quot;*css&quot;&lt;/code&gt;), and what resources should be served by a new route name (&lt;code class=&quot;language-text&quot;&gt;&quot;/foo&quot;: &quot;foo&quot;&lt;/code&gt;).&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// bs-config.js&lt;/span&gt;

module&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;exports &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token string-property property&quot;&gt;&quot;files&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;*html&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;*js&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;*css&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token string-property property&quot;&gt;&quot;server&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token string-property property&quot;&gt;&quot;port&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3000&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token string-property property&quot;&gt;&quot;routes&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token string-property property&quot;&gt;&quot;/foo&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;foo&quot;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt; Checkout all the options available in the &lt;a href=&quot;https://www.browsersync.io/docs/options&quot;&gt; docs&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt; For this example, I have also included an entry point at index.html, and an additional html file to try a new route:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;html&quot;&gt;&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- index.html --&gt;&lt;/span&gt;
&lt;span class=&quot;token doctype&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;!&lt;/span&gt;&lt;span class=&quot;token doctype-tag&quot;&gt;DOCTYPE&lt;/span&gt; &lt;span class=&quot;token name&quot;&gt;html&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;html&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;head&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;meta&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;charset&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;utf-8&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;title&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;INDEX&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;title&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;head&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;body&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
      This is the index
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;body&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;html&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;html&quot;&gt;&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- foo/index.html --&gt;&lt;/span&gt;
&lt;span class=&quot;token doctype&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;!&lt;/span&gt;&lt;span class=&quot;token doctype-tag&quot;&gt;DOCTYPE&lt;/span&gt; &lt;span class=&quot;token name&quot;&gt;html&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;html&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;head&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;meta&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;charset&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;utf-8&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;title&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;FOO&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;title&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;head&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;body&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
      This is a foo
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;body&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;html&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now that you have a sample project outlined, start the server.&lt;/p&gt;
&lt;h2&gt;3. Start the web server&lt;/h2&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;$ browser-sync start --config bs-config.js&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Browser-sync will open your default web browser and load the index.html file:&lt;/p&gt;
&lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/62ecabb87971d16004c27edb26291d3a/38124/https2.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 89.24050632911393%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAASCAIAAADUsmlHAAAACXBIWXMAAAsTAAALEwEAmpwYAAACDElEQVQ4y6WT227UMBCG8/5vAjdwiRAXRaqQgIpW2kLoJovXseP4HMfxIadN0GaptqBWBfFpbEuWftvzzzgB6ZcUpPssJyUmVVWWZVEU5XMURbHZbBJcVnAPa0K0EIwxa23f991z9H0vhEhiiK1z/TAs/06y/AfJYZ6XNeZlXpZ1LOf1uL3OJw4PmOc5YQWiXJQVryinjDEudpAicsyfMSaEoLRSK8aYLp5pmibpOBk6O/Vh6twYm9Zwq5lgZUkIZYxzTkglla6N0bqu69oYE0KIMYYQkqtM34D4KXOfM/8x85df6/eb+jpTlFa6rq219Urbtl3XhVU3DMO4kry7Kl9fopcX6MVF8epD9fameXPdXv/wGBUAAExL0zQhxLZ1p/x/M8xoTklRy0pQLBjWgngrx95DCG9vb7c/tlJpa+1D285iTGi2AwDibAd2AOYA3uVA6boiJM/zEhNjbevcNE2PlMqYhoujI1xIqZTUmgvZdR1C6FuaZvmOC+lD8D488uynGgAhtM2yfVEAWDDOpdKx6/7QJ7+Sue+HE+M4Yoz3cC+VUlorrZ331lrn/Vqk6JwPMT5y8+kUhDHCmJBKSMm4aKwdx2m4p+/7YRifFiOUpt+zfMe4GIbhMB3+6mOcxBDCu7stgJBzHmM8HA7TdIozTxk2K6UJIfzY26yibK2FFlIJqVrnbNs6738CXAMAYxikvVgAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;https2&quot; title=&quot;https2&quot; src=&quot;/static/62ecabb87971d16004c27edb26291d3a/f058b/https2.png&quot; srcset=&quot;/static/62ecabb87971d16004c27edb26291d3a/c26ae/https2.png 158w,
/static/62ecabb87971d16004c27edb26291d3a/6bdcf/https2.png 315w,
/static/62ecabb87971d16004c27edb26291d3a/f058b/https2.png 630w,
/static/62ecabb87971d16004c27edb26291d3a/40601/https2.png 945w,
/static/62ecabb87971d16004c27edb26291d3a/38124/https2.png 953w&quot; sizes=&quot;(max-width: 630px) 100vw, 630px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
&lt;p&gt;Test out the router by navigating to &lt;code class=&quot;language-text&quot;&gt;localhost:3000/foo&lt;/code&gt;, and you should see the content of &lt;code class=&quot;language-text&quot;&gt;foo/index.html&lt;/code&gt;&lt;/p&gt;
&lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/53fb1a31f3e7b2365a944ce9d58c4e46/a0b80/routes.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 86.70886075949367%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAARCAIAAABSJhvpAAAACXBIWXMAAAsTAAALEwEAmpwYAAAB60lEQVQ4y52Sy27UMBSG8/6PQFewgyegKwQLFuyAUTuaJM7Fju3El8S32M5lgiajbtopoH6yJUv2J53zHyfp8edjdoR53kAIEaqqGkJE/gqltCyLw+GQENrxjgWl9HDBOTfP8/Iv5mnSxiRTjPM8b28iOZ/P21tJeiH2etV1a224GIa9CaWU2u/0BeWcizGGnXEcrbWJRpVSYlDaKDlIxjuKG9g0aI+NUkohhFJKIYSUUimltfbejztJRfpumNohdkPEYiyaHuAeYsZYJ2Xf9z3nF80YY6xVWltrwxPJp6/o7h7f3eN3n5v3X9jH7/rDN/XjpFBdYEK44MZaa52xdl3X5z1LThiFkjW8hbxF3ojo+im4NM1+H36dylTKYRzHZVleRptARDJQlzUCJUzz8pSVxzRnXCCEAAAtbZW6lLpt2w257ViDCWlbhClqcIMJRI1zIwDg4fEhy4FSes95+t85r+taFEUOiqKoIMIdY30/zPPyXH4Zw7ZtIYSqqgAoGBcdY1JKa53WJsZpX9GHMM/zbXlZlrqGGJOuY1zIjjFjbIjRe+9D8N67cYzTdFte1xUAkJ5OeQ64kD74ZVlu9PyanGVZloOyhsMwXN9c0znvhyuvypiQGkJCabOPgMueC8n45Zda65TWPsQ/yv/HM3oTZzEAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;routes&quot; title=&quot;routes&quot; src=&quot;/static/53fb1a31f3e7b2365a944ce9d58c4e46/f058b/routes.png&quot; srcset=&quot;/static/53fb1a31f3e7b2365a944ce9d58c4e46/c26ae/routes.png 158w,
/static/53fb1a31f3e7b2365a944ce9d58c4e46/6bdcf/routes.png 315w,
/static/53fb1a31f3e7b2365a944ce9d58c4e46/f058b/routes.png 630w,
/static/53fb1a31f3e7b2365a944ce9d58c4e46/40601/routes.png 945w,
/static/53fb1a31f3e7b2365a944ce9d58c4e46/a0b80/routes.png 955w&quot; sizes=&quot;(max-width: 630px) 100vw, 630px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
&lt;p&gt;Serving a local site is just that quick. If you don’t know where to start with your bs-config.js file, you can have browser-sync generate one for you:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ &lt;span class=&quot;token function&quot;&gt;mkdir&lt;/span&gt; testserver &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token builtin class-name&quot;&gt;cd&lt;/span&gt; testserver
$ browser-sync init
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;BS&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; Config &lt;span class=&quot;token function&quot;&gt;file&lt;/span&gt; created bs-config.js
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;BS&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; To use it, &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; the same directory run: browser-sync start --config bs-config.js&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In the generated config file, you find all the options that are used internally, but there are many more described on the &lt;a href=&quot;http://www.browsersync.io/docs/options/&quot;&gt;website&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;module&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;exports &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token string-property property&quot;&gt;&quot;ui&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token string-property property&quot;&gt;&quot;port&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3001&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token string-property property&quot;&gt;&quot;weinre&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token string-property property&quot;&gt;&quot;port&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;8080&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token string-property property&quot;&gt;&quot;files&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token string-property property&quot;&gt;&quot;watchOptions&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token string-property property&quot;&gt;&quot;server&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token string-property property&quot;&gt;&quot;proxy&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token string-property property&quot;&gt;&quot;port&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3000&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token string-property property&quot;&gt;&quot;middleware&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token string-property property&quot;&gt;&quot;serveStatic&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token string-property property&quot;&gt;&quot;ghostMode&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token string-property property&quot;&gt;&quot;clicks&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token string-property property&quot;&gt;&quot;scroll&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token string-property property&quot;&gt;&quot;forms&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token string-property property&quot;&gt;&quot;submit&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;token string-property property&quot;&gt;&quot;inputs&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;token string-property property&quot;&gt;&quot;toggles&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token string-property property&quot;&gt;&quot;logLevel&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;info&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token string-property property&quot;&gt;&quot;logPrefix&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;BS&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token string-property property&quot;&gt;&quot;logConnections&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token string-property property&quot;&gt;&quot;logFileChanges&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token string-property property&quot;&gt;&quot;logSnippet&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token string-property property&quot;&gt;&quot;rewriteRules&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token string-property property&quot;&gt;&quot;open&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;local&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token string-property property&quot;&gt;&quot;browser&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;default&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token string-property property&quot;&gt;&quot;cors&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token string-property property&quot;&gt;&quot;xip&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token string-property property&quot;&gt;&quot;hostnameSuffix&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token string-property property&quot;&gt;&quot;reloadOnRestart&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token string-property property&quot;&gt;&quot;notify&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token string-property property&quot;&gt;&quot;scrollProportionally&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token string-property property&quot;&gt;&quot;scrollThrottle&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token string-property property&quot;&gt;&quot;scrollRestoreTechnique&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;window.name&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token string-property property&quot;&gt;&quot;scrollElements&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token string-property property&quot;&gt;&quot;scrollElementMapping&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;For example: to &lt;a href=&quot;https://www.browsersync.io/docs/options#option-https&quot;&gt;test your application over https&lt;/a&gt;, set &lt;code class=&quot;language-text&quot;&gt;&quot;https&quot;: true&lt;/code&gt; right beneath your server options. When browser-sync opens the browser with your entry point, the browser should warn you that the connection isn’t safe:&lt;/p&gt;
&lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/7e4bd9e8285b132a6d132d57e874ca3f/ecf19/https.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 74.68354430379746%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAPCAIAAABr+ngCAAAACXBIWXMAAAsTAAALEwEAmpwYAAABn0lEQVQoz42SW27bMBBFteguoAsI0M0UBbqHfgSoCzgWoBdJUa4o8THkDCklTiErseUmaHq+yI/Dmbmc7LD78SvflYe8KkohhGhbxlj7EUKI3W6X8VZ2stOd7DvZCqG1DsF/SAhBKZUR4TzPcZqmeZ5PpxQj/R8ppQwAEJGIgjFQ5Ei0XmlzeBdEzLz3hBifTrD/WX3+RIgppbjhH6+cZSKK0euxP+yttcYYd8YYAwDplfhmohc5xmidK6qqKIo8z+uqqsoyz3PGmHVWKaW1Nsb81UIG8FIZnBOMyU62bdsdu7YVqlfDOCiljsdjr9Q4jm9lWE8hBGOM3mCMvTCOo3WAFLf6VUZEAFhmtnZpcVHNitbG6jGhOz3SPNHFfw3sXHkYB2ttirdpx/T8lB54+vIt3n2l7/f0/EgBb2VEXOO9aJcJU6TB0p7HB06sX66It2k75xhjnPG6WcJumqYsy7qumwXGWf1bNlrJebpOfSNzzoUQjHMpZdd1zjnw4AC898u3WwcQ8J0lIQreq14ppfq+B4BpmtZH193Y7NtV/gP6AE5l/i+40gAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;https&quot; title=&quot;https&quot; src=&quot;/static/7e4bd9e8285b132a6d132d57e874ca3f/f058b/https.png&quot; srcset=&quot;/static/7e4bd9e8285b132a6d132d57e874ca3f/c26ae/https.png 158w,
/static/7e4bd9e8285b132a6d132d57e874ca3f/6bdcf/https.png 315w,
/static/7e4bd9e8285b132a6d132d57e874ca3f/f058b/https.png 630w,
/static/7e4bd9e8285b132a6d132d57e874ca3f/40601/https.png 945w,
/static/7e4bd9e8285b132a6d132d57e874ca3f/ecf19/https.png 948w&quot; sizes=&quot;(max-width: 630px) 100vw, 630px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
&lt;p&gt;Click on &lt;code class=&quot;language-text&quot;&gt;Proceed to localhost (unsafe)&lt;/code&gt; to load your content.&lt;/p&gt;
&lt;p&gt;Easy peasy.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Service workers]]></title><description><![CDATA[A service worker is a script that sits between a web page and the network, acting as a proxy for network requests: if the network is…]]></description><link>http://katieleonard.ca/blog/2016/2016-10-15-service-workers/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2016/2016-10-15-service-workers/</guid><pubDate>Sat, 15 Oct 2016 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;A service worker is a script that sits between a web page and the network, acting as a proxy for network requests: if the network is available, the request is passed on to the target url; if the network is not available, the service worker will handle the request itself by checking cached responses or or queuing the request for synchronization once the network is available. Service workers are bridging the gap between native mobile applications and traditional web applications that require a network connection to function. Sometimes called progressive web apps, these applications enable a seamless offline experience when the user is not connected to a network.&lt;/p&gt;
&lt;!--more--&gt;
&lt;p&gt;Service workers can be used for data synchronization in the background, but data fetching and sync-ing are only one of the ways we can leverage this API. We can:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;use background resources to perform client-side compilation of assets  (useful for web development)&lt;/li&gt;
&lt;li&gt;pre-fetch data that the user is likely going to need in the near future (think photo albums or playlists)&lt;/li&gt;
&lt;li&gt;share large data sets between multiple pages&lt;/li&gt;
&lt;li&gt;notify mobile users of updates via push notifications&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For example, &lt;a href=&quot;https://www.washingtonpost.com/&quot;&gt;The Washington Post&lt;/a&gt; uses service workers to send push notifications of breaking news content to users of their web application on android.&lt;/p&gt;
&lt;h2&gt;How do they work?&lt;/h2&gt;
&lt;p&gt;Service workers rely on the &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise&quot;&gt;Promise API&lt;/a&gt; — a Promise is a proxy for “a value that may be  available now, or in the future, or never.” They also use the event emitter pattern, where listeners are registered to handle specific events, such as &lt;code class=&quot;language-text&quot;&gt;fetch&lt;/code&gt; requests.&lt;/p&gt;
&lt;p&gt;To employ a service worker you must first register a script with the service worker API: &lt;code class=&quot;language-text&quot;&gt;navigator.serviceWorker.register(&apos;./sw.js&apos;)&lt;/code&gt;. Checkout the following example (&lt;a href=&quot;https://gist.github.com/keighty/ec1a37a0f6475d7cdf2db64b01eff445.js&quot;&gt;get the gist&lt;/a&gt;):&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;html&quot;&gt;&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- index.html references the javascript application --&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;html&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;body&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;h1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Service worker test app&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;h1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;script&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;./app.js&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token script&quot;&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;body&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;html&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// app.js&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;register&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;sw.js&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// register a worker script with the service&lt;/span&gt;
navigator&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;serviceWorker
  &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;reg&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// do the following if registration is successful&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;reg&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;installing&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;// first visit or fresh reload of the worker&lt;/span&gt;
      console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Service worker installing on registration.&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;reg&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;waiting&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;// a worker may be installed but waiting for another worker to stop&lt;/span&gt;
      console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Service worker already installed on registration.&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;reg&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;active&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;// pages from the same origin may share a service worker&lt;/span&gt;
      console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Service worker already active on registration.&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;catch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// if registration is unsuccessful, tell us why&lt;/span&gt;
    console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Registration failed with &apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; error&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// sw.js&lt;/span&gt;
console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;inside registration script&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;install&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Service worker installed.&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;activate&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Service worker activated.&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Service workers can be registered with a specific origin and path to watch. Since they run in a background thread with a context separate from the application javascript, service workers have no DOM access. So don’t try to perform synchronous work (like accessing LocalStorage) or update the DOM from a service worker.&lt;/p&gt;
&lt;p&gt;Running this example code sends some output to the console:
&lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 552px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/0fbd8bbce8e8cd7366fed50324cfd9c4/08c0b/service-worker-demo1.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 68.35443037974683%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAOCAIAAACgpqunAAAACXBIWXMAAAsTAAALEwEAmpwYAAACHUlEQVQoz21S6W7bMAz2+7/LXmD7tXUY9qtImh5xDnuJrcOHZOuwLlvi4LTAuq0fPhIkJYogqWz35fPdj09ftz9fnvLd4+Pj0/P2YbfZbI+nc43wuSjvN9v7zcNuf3zZH/L8cDye8jy/+/b9aXuXlfv9+fx8Kk8EY1xXqK4IwYSQaZpCcM65pmmL07nO83NR/KpRURQIodPpXF2KjI/jZMIwCM6HGuGyvBBKOWfOWees9845KzjTqOq6jgmJMZZSKqWk0hmkBQyDoCB6mBVEC5DgJm9MafU/QgZxBt3CWIKmie0TPyYnYTawOAgaZrvSS3AiLf71rXfJi4cwgRuB5SCuoCkoBLJabVmBRKAI8AOwA3h1S3mXnGaX7Ah2SEORxCVN7U13SdZJ06Ro0u3tqEpxTin9XTkGmPXatu1hIis9B9OC62FqwN7iugZVrXP5p3LPWNu2oxA1Qn3PCKEI067vKSGcc0LoKETbtgPvX28qpYwx4zhyzjOEEKV04Hwc+DSZjummV1Iqztg4DAihepXry4VdKlRVV4xx0zTee2NMZoxp244xvu5Oa2Ot1jrGCAAxxmVZjDHeO2Gjsc57Z60db/DeZz4E2rQd45jQrmeYrN5Hq/0TMcZcr1chRGatrREhtK0Rbrv+WiFCm8kYIeQohJQqxphSuqm3UQ/DUJblMAxZmNNywzwvMcZ5NeYQgl8RQgj/f6zXhpdl+Q3afRfG0xJREAAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;service worker demo1&quot; title=&quot;service worker demo1&quot; src=&quot;/static/0fbd8bbce8e8cd7366fed50324cfd9c4/08c0b/service-worker-demo1.png&quot; srcset=&quot;/static/0fbd8bbce8e8cd7366fed50324cfd9c4/c26ae/service-worker-demo1.png 158w,
/static/0fbd8bbce8e8cd7366fed50324cfd9c4/6bdcf/service-worker-demo1.png 315w,
/static/0fbd8bbce8e8cd7366fed50324cfd9c4/08c0b/service-worker-demo1.png 552w&quot; sizes=&quot;(max-width: 552px) 100vw, 552px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h4&gt;NOTE: A single service worker can control many pages (so be careful with global variables).&lt;/h4&gt;
&lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 553px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/bf2c2e6a84a8e9c2542ecc49dfdcc0f4/74cfa/service-worker-demo2.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 59.49367088607595%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAIAAADtbgqsAAAACXBIWXMAAAsTAAALEwEAmpwYAAACC0lEQVQoz02R224TMRCG9zV5G16CO56Bi14ggZqECKg4SqXJbmiyaTbp2o734ON6T/Z6kANF/WX9+mXNN5qxo9Xs3fLr1eL7zYf5cr5YzOaL6+vZ9Wy+/Pjp9tfdarUOJ05WcbLdbg+HLEmS29u7L5+X6f3P6LBJ0sMmvk/i9Tper+L1Oonj35sNyh85q6UQjNUlys8Pe0wILat0t8uybJ/ussMuYkIY03EuhBQ5JqfHvKq51sa5abDO2lG3nSwKgVHBBCkrSs9N0zTGnM808gDejTAocD30HFwXvBNTr6a28rb3HfNTD7aBUYHtAMB7DwBKyggAwPbAH0AevULeFMB2wFIQGcgTmBL4HjQGlnp59PIEfgoogFLqCRYPoHLoBZgC2jJgbAsNhmoTXGShoCGh1xOstb7AbgS+94aCKXy18RqHUdsaNA6Xrvctg46BKb3t/4/9BE/WawRdGSoaBFbDM/lnDhfs385KRfQiJuTxlJdVfXzECFNCMMaYUooQ4pwRhFQtMEKUUimlCD8j9odjRAguCso501qZtq95y2TXtq3WSmtNCCnOlGD8o0yoLDvTDcNgrfV+yjGNtG6qquZcKK2NMUJKE9Q2xjDOBRO4pi/il6/yN+/ZNwAYxqEsS60UplXUD9ZdZK21zg3DaO3f6MYQnZ3c2+Lm9elqJdPwuNPU94OfpqrmfwCZ2Jx3CBPZuAAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;service worker demo2&quot; title=&quot;service worker demo2&quot; src=&quot;/static/bf2c2e6a84a8e9c2542ecc49dfdcc0f4/74cfa/service-worker-demo2.png&quot; srcset=&quot;/static/bf2c2e6a84a8e9c2542ecc49dfdcc0f4/c26ae/service-worker-demo2.png 158w,
/static/bf2c2e6a84a8e9c2542ecc49dfdcc0f4/6bdcf/service-worker-demo2.png 315w,
/static/bf2c2e6a84a8e9c2542ecc49dfdcc0f4/74cfa/service-worker-demo2.png 553w&quot; sizes=&quot;(max-width: 553px) 100vw, 553px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
&lt;h2&gt;Developing with service workers&lt;/h2&gt;
&lt;p&gt;Service workers can only function in a secure context, which means that you can only register a service worker from a web application that is served over &lt;code class=&quot;language-text&quot;&gt;https&lt;/code&gt;. One option is to use &lt;a href=&quot;https://pages.github.com/&quot;&gt;GitHub pages&lt;/a&gt; to deploy your application, as these pages are generally served over &lt;code class=&quot;language-text&quot;&gt;https&lt;/code&gt;. Another option is to use a local web server (&lt;code class=&quot;language-text&quot;&gt;localhost&lt;/code&gt; is considered semi-secure).&lt;/p&gt;
&lt;p&gt;I use &lt;a href=&quot;https://www.browsersync.io/&quot;&gt;Browser-sync&lt;/a&gt;, a super light-weight easy to start web server. In my project directory, I start the browser-sync server and set it to watch my javascript files:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ &lt;span class=&quot;token function&quot;&gt;npm&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; -g browser-sync
$ browser-sync start --server --files *.js
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;BS&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; Access URLs:
 ----------------------------------
       Local: http://localhost:3000
    External: http://10.0.0.8:3000
 ----------------------------------
          UI: http://localhost:3001
 UI External: http://10.0.0.8:3001
 ----------------------------------
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;BS&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; Serving files from: ./
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;BS&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; Watching files&lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;.&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Browser-sync is so helpful, it will even open a browser window for you. :awthanks:&lt;/p&gt;
&lt;p&gt;Don’t forget to checkout the Chrome developer tools, which can be super helpful in creating different states for your service worker&lt;/p&gt;
&lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/a0252f3437951d25c66b4ef01df7b692/99072/service-worker-dev-tools.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 74.68354430379746%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAPCAIAAABr+ngCAAAACXBIWXMAAAsTAAALEwEAmpwYAAACZ0lEQVQoz12RbW/cKhBG/f9/Vb9UbdPotr1xsomddda79hovGPMOA4a5cqq2Vz16hBBiBjhU/3758LW+a5vX5+eXw+H5Mgw3yh7q+tOnz3df7u7v7x8f67qu26btjsdj07Rtezwe64fH+sfXalnFygVjy3S9Mkp9gG3bQgjeee/3IQQIIUBM1nkx325soYwJIaSUFdF4s3hRSCw+UTzzdFq3N4G9QGrxJHBQBbGUoEoQ6BnmiL+ocsFccCslbiUkTOISxbClGDNmc7OKE4OIuegJ1YBBYsl/ivEvHMWoEMs+t6NT9DtFdHMJal8p5f97K0op55wxujDGuGD94zK8LNLwqePXlqy+ffrO3n4sq+LrSinVxnjnrLVKqao/nbquW5ZlXVepDSenW/OZSmfP917OznnbfYTgU9rSTiwl55xThG1LFSHkcDj0fa+Ucm63q4yXUmglAcBZa6wFgPeHlLRhTAUSCg0hxGocR0qpEEIpZZ1zVon5TOYbF+5vHaUo5bkAyZblfDQBq77vm6bpuk4IYX0oXuTpHwfbTOd5vpGZUjovwnp2zqJHTzHwIk9FX3dh4zjW9QMhRGttrMvJb+pqPWgj+brwqZMKUsYcA4IuaihqRDMVeS4bVPM8E0KMMXrHRM2iGKNTEQBi8sM3T5rd1JZTjAn8e0IMLkWoxmFnHEchpdY60FfgfeQncLsTyBjEFfgZJAE5gZhAzRATwN58/+fL5TKOI+fcaA3rEJe3yF4jbcApSBvIKc5PQNtIX4D34Hf5P6n6/kwp896/X1sF78Cse6wACPsJ3oI3e5wG8BDj7+L/APZNTth6ewgtAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;service worker dev tools&quot; title=&quot;service worker dev tools&quot; src=&quot;/static/a0252f3437951d25c66b4ef01df7b692/f058b/service-worker-dev-tools.png&quot; srcset=&quot;/static/a0252f3437951d25c66b4ef01df7b692/c26ae/service-worker-dev-tools.png 158w,
/static/a0252f3437951d25c66b4ef01df7b692/6bdcf/service-worker-dev-tools.png 315w,
/static/a0252f3437951d25c66b4ef01df7b692/f058b/service-worker-dev-tools.png 630w,
/static/a0252f3437951d25c66b4ef01df7b692/99072/service-worker-dev-tools.png 842w&quot; sizes=&quot;(max-width: 630px) 100vw, 630px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
&lt;hr&gt;
&lt;h2&gt;MOAR Resources&lt;/h2&gt;
&lt;p&gt;For more about the service worker API, checkout these resources:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the &lt;a href=&quot;https://www.w3.org/TR/service-workers/&quot;&gt;W3C spec&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;the &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API&quot;&gt;MDN docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;and the &lt;a href=&quot;https://github.com/mdn/sw-test/&quot;&gt;example&lt;/a&gt; &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API/Using_Service_Workers&quot;&gt;https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API/Using_Service_Workers&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[The EventEmitter Pattern and the Event Loop -- a timeline]]></title><description><![CDATA[The EventEmitter pattern is a derivative of the Observer pattern: an object can notify a set of observers when a change in its state occurs…]]></description><link>http://katieleonard.ca/blog/2016/2016-10-14-event-emitter-and-event-loop/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2016/2016-10-14-event-emitter-and-event-loop/</guid><pubDate>Fri, 14 Oct 2016 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;The EventEmitter pattern is a derivative of the Observer pattern: an object can notify a set of observers when a change in its state occurs.&lt;!--more--&gt; Consider the following example using the EventEmitter pattern:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; EventEmitter &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;events&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;EventEmitter
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; fs &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;fs&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;findPattern&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;files&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; regex&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; emitter &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;EventEmitter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

  files&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;forEach&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;file&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    fs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;readFile&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;file&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;utf8&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;err&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; content&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; emitter&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;emit&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;error&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

      emitter&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;emit&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;fileread&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; file&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

      &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; match
      &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;match &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; content&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;match&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;regex&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        match&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;forEach&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;elem&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
          emitter&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;emit&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;found&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; file&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; elem&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; emitter
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// fileA.txt contains the words &quot;hello blah blah blah&quot;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// fileB.json is empty&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// fileC.md does not exist&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; files &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;fileA.txt&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;fileB.json&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;fileC.md&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;

&lt;span class=&quot;token function&quot;&gt;findPattern&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;files&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token regex&quot;&gt;&lt;span class=&quot;token regex-delimiter&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token regex-source language-regex&quot;&gt;hello \w+&lt;/span&gt;&lt;span class=&quot;token regex-delimiter&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token regex-flags&quot;&gt;g&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;on&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;fileread&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token parameter&quot;&gt;file&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;file&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt; was read&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;on&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;found&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;file&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; match&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;Matched &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;match&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt; in file &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;file&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;on&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;error&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token parameter&quot;&gt;err&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;Error emitted: &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;message&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Some of the script is executed synchronously, but the real work is done asynchronously. The EventEmitter pattern takes advantage of the event loop to work efficiently.&lt;/p&gt;
&lt;p&gt;Keep the following schematic in mind as you parse through the execution of this script:&lt;/p&gt;
&lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/f78644d8afea9f6e939244ce846a5d10/7131f/event-loop.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 62.65822784810127%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAANCAIAAAAmMtkJAAAACXBIWXMAAAsTAAALEwEAmpwYAAACH0lEQVQoz02S647aQAyFef/3qfoGi1btHwJsbpCwLCEhyUwmc83c7IqwrXo0P8aWPtk6PhsAEEKoVXIV55wQQilt27auq/pyJbOmdBq7LzlcFbnLsbFqPh4/NgAYY8T/5L1/dULwPkSvGdI8ktwMFYgGVQeqxyirqt4gQIzhhVlrnXNSqcejb5qGkHEWmp23l98/267nyiAtcTrDfEXdns/nDTMw6UA0iiVIzixr9NSRsZ/nmTGmpJxm0d7q9rTj9wz4DcUd1IBBPOETxcvo6xmuDLUSKBrUPQT72iWEqDg12Q/dZuAXNATMFDVFxHWyR91Sn35K78f+Yccq8A6iX1nw3mtjbERYa+cDm0XbPZRSaZpuEHGitK0/T+dTWRZV/TleDqorULVoyHoCsZryxBljZVGkaVoUxfv7+xO+3ZpjmmZZdjqdiqLMk1/jvUL18JpJpbUx2izOhwhICNnv97vdLkmSt7e3F3z7OB4+joc8S9PjMSvK7tEvi9VacyH6+5X3VzF+BU2HYTgcDkmy2+/32+32CQ/DcP7qqq/+0gxVM9zbh5ISEWMI1vmwCMc7WBhayuhQlGWeZd9rA4BUSixxXkAuUbmnK9Z+ux1jtNb9y4/WZlmstRYAkiTZvCIVvHd2kYLbxVijord/n8PoXp/onTVKK0kpdc7lef6cHMIzYQDgnPNucYY7zZxiTs9Oc8VGKydnxFoyb4117nXnPwop2ySRZoD/AAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;event loop&quot; title=&quot;event loop&quot; src=&quot;/static/f78644d8afea9f6e939244ce846a5d10/f058b/event-loop.png&quot; srcset=&quot;/static/f78644d8afea9f6e939244ce846a5d10/c26ae/event-loop.png 158w,
/static/f78644d8afea9f6e939244ce846a5d10/6bdcf/event-loop.png 315w,
/static/f78644d8afea9f6e939244ce846a5d10/f058b/event-loop.png 630w,
/static/f78644d8afea9f6e939244ce846a5d10/7131f/event-loop.png 710w&quot; sizes=&quot;(max-width: 630px) 100vw, 630px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
&lt;p&gt;&lt;em&gt;image credit: Mario Casciaro and Luciano Mammino from Node.js Design Patterns. Colour notations are mine.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;The first set of operations happen synchronously:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;call &lt;code class=&quot;language-text&quot;&gt;findPattern&lt;/code&gt; with the file list and regex pattern&lt;/li&gt;
&lt;li&gt;create a new event emitter&lt;/li&gt;
&lt;li&gt;submit &lt;code class=&quot;language-text&quot;&gt;readFile&lt;/code&gt; I/O request for fileA.txt to the event demultiplexer&lt;/li&gt;
&lt;li&gt;submit &lt;code class=&quot;language-text&quot;&gt;readFile&lt;/code&gt; I/O request for fileB.json to the event demultiplexer&lt;/li&gt;
&lt;li&gt;submit &lt;code class=&quot;language-text&quot;&gt;readFile&lt;/code&gt; I/O request for fileC.md to the event demultiplexer&lt;/li&gt;
&lt;li&gt;return the event emitter&lt;/li&gt;
&lt;li&gt;register &lt;code class=&quot;language-text&quot;&gt;fileread&lt;/code&gt; listener on the event emitter&lt;/li&gt;
&lt;li&gt;register &lt;code class=&quot;language-text&quot;&gt;found&lt;/code&gt; listener on the event emitter&lt;/li&gt;
&lt;li&gt;register &lt;code class=&quot;language-text&quot;&gt;error&lt;/code&gt; listener on the event emitter&lt;/li&gt;
&lt;/ul&gt;
&lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/a6867ac91d91adc958750bb0b5868913/e1031/event-emitter-1.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 81.64556962025317%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAQCAIAAACZeshMAAAACXBIWXMAAAsTAAALEwEAmpwYAAAC90lEQVQozzWQ23KqSAAAqayIooignmhMojFo1MFh7hdgAG9odLd2//9rTplTW9Wv/dBtDc13qHggVZ+pSZr53PjMuFA9IWUnykNsSuU7y9+22Wecz0G+APkEpF0g7VhaQ3P1uAiYCETdZ4cuzh127NHjnF2WifnY5COQPiOzjvMdKD5A/gXMO8g8oJxYWgNz6VDtU9ZhxzYpBzi/0luB6jXaD3e6saGNnfCTfLYyc5BNQfYM0hHQY5B2Y2X9Ovzt0H2bXZ71IdTnPqvnrGyi7C+o7SRvodKJ0zeTbkvsrXV3o5pb0QQ/xNL6dfgnwFmAVShPA1EMhHTluSfrAT968uiKYyDLz5MGN9BnzCPMhdze/C+PqvsL5HMoF7hYYRlhvqRyQUQPFfZON9Z0scfbb7a5wNU5WezR4vCgT7kNpDWs7m9QQBhLKmKURoAsYkbjZA75544Nt2ySs+gkZyWalfi9xNEJfVRompPHsLC6ryBbQDzT16WqY11F6gpkOqNmik0P6llF8L8sOsGvOlnXyfqSgG84r3ALSsuv7mKXEAAFVgzLiOglUSvCA5i1UemQ/Vgz8M1fMjzNyWKPXg2eV+i9xB0krKC6wx153akQMH+DG1vxB/uxlDuAv6T06yKiE3zJ8STDH4ekT6mHeXsnrEl1a9LCo9JGhY0qBwgHiFb8oAnE01Y6sRzQtBszH4ow4QPE3Vg0tvJxe7y/t7HpJrSNjJMUzo/W2MqnjWzHYkzoXLCJUJEiMCdLRZEhK00+JQ0Qt56rW5cKF6dNWLShsmnxhMyQqa9Sbis14cKThacPUy4iRV8Ze+NsqehMMD8RD9ljRSjKHi1sfHxN06om4szfpLRj/QR0K0k9koWYvXM6IXTOyZjQdvzT/Fx+d2k5So9+cXL1dWbO0f7Q0yaUYqQKXx562S2o6k5eu+LSQlmLZA42Di5bSWaN9zcXm74oXVW6pGriyuXlULGAVUGae6L0TR1WF1fVrv6vo29dVraS1EnyFtS/AZ0mpFo0g0FlAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;event emitter 1&quot; title=&quot;event emitter 1&quot; src=&quot;/static/a6867ac91d91adc958750bb0b5868913/f058b/event-emitter-1.png&quot; srcset=&quot;/static/a6867ac91d91adc958750bb0b5868913/c26ae/event-emitter-1.png 158w,
/static/a6867ac91d91adc958750bb0b5868913/6bdcf/event-emitter-1.png 315w,
/static/a6867ac91d91adc958750bb0b5868913/f058b/event-emitter-1.png 630w,
/static/a6867ac91d91adc958750bb0b5868913/e1031/event-emitter-1.png 803w&quot; sizes=&quot;(max-width: 630px) 100vw, 630px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
&lt;p&gt;Once the I/O operations are submitted to the event demultiplexer, they will return in the order in which the requests are fulfilled. In this example, fileC.md does not exist, so the event demultiplexer submits the result along with the handler to the Event loop.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The event loop runs the result through the callback for fileC.md, which &lt;strong&gt;emits an error event&lt;/strong&gt; (line 9)! The EventEmitter adds the error handler to the event loop.&lt;/li&gt;
&lt;/ul&gt;
&lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/7ed07ece0a8fb8147171c21f409a6734/e51a6/event-emitter-2.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 84.17721518987341%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAARCAIAAABSJhvpAAAACXBIWXMAAAsTAAALEwEAmpwYAAAC0ElEQVQ4y3WT2W7bRhiFVVjkcLhaSyK4blPUTmSL26ycjatEipIbpwl61QfITd//BQrazoKgBc7FYIAP55/zn5kF8vDakIVSayWvjF6Ieim7gBhIS4jLiLIFpyFhdiJ+VCpnvuoDWvjYhKQNSQ1RCXBrZxVANcyFlah5LK1Y/h88LARdiiJQjx7rlrxeyXGtTytzCoi0Y24nxX+QX50B3vvyvDH9Uo5ucfaYgUhZiZ4nlYMbJxMg++YMfnAGqIp4tdbDQraRqjw1wmK8Krt1s7f5Q1B0IDdWLL7XCxyYI8gUyEsrb3ykAiIhby3UXDfl+8/xghEr0SHhMCvcvPBQ4ePpANInODKjnWmPlm5x9OneyZRDtIP1RVIFVG2H7Loi6R/57QH9WpPtgH6pSMS4kxV28gKbiNGw+uiJh1AcXfG4Em3A95AN88SsCro7oe0R3ezxbY9/LumyYAF5gqexcw0yA8X7UJw3Zoj0ydedS1qAuoVur2u6PaK3Pd6O6Pc9vhvRuwFtFJvHX97s5KWDaivVTqpAKp1cXcRqJeWbjkeU3435bT+Zv2nI9oh+a0mACyuRs8tyhKSBuLbjaZ9WIkAqfrqTa8He9tl8NyWE/8xuDvj+lN8ccEj4K8nAc9qhHn1mLhmFbHDoASTFbCs3iu7GzErEfCfdrFgLFhK+4GxZsIt7ebH7sqrQjCBXdirtVMNczu70dUXRh+zpRk31yNQ8VlYi57tJIJ1Ge4EvzfGSM5fWEHez+/rmQem/kZ0ZwDooaoA0pMYrapBrO+Yv2NeGRWZcyv6qGgJ1TP7q+s/SlX2k67UUXlZBUju4dZ4/GSmfsOeqywletI8hayI5XJ27D/9gX549eV5ps5J6U5ZL3UfVo98Ofn30q0/uVP4GFo3DDi5tZ5E5ubj0SOUyY2eVk+uAiZByH7WQlJAYl9eQlQ6pHXqAfISknoKYEpH/Ag5eov/6vKfrAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;event emitter 2&quot; title=&quot;event emitter 2&quot; src=&quot;/static/7ed07ece0a8fb8147171c21f409a6734/f058b/event-emitter-2.png&quot; srcset=&quot;/static/7ed07ece0a8fb8147171c21f409a6734/c26ae/event-emitter-2.png 158w,
/static/7ed07ece0a8fb8147171c21f409a6734/6bdcf/event-emitter-2.png 315w,
/static/7ed07ece0a8fb8147171c21f409a6734/f058b/event-emitter-2.png 630w,
/static/7ed07ece0a8fb8147171c21f409a6734/e51a6/event-emitter-2.png 783w&quot; sizes=&quot;(max-width: 630px) 100vw, 630px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
&lt;p&gt;In the meantime, the event demultiplexer has fulfilled the I/O request for fileB.json, and added the result and the callback to the event loop.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The event loop runs the result through the callback for fileB, which emits a &lt;code class=&quot;language-text&quot;&gt;fileread&lt;/code&gt; event (line 11). The EventEmitter adds the &lt;code class=&quot;language-text&quot;&gt;fileread&lt;/code&gt; handler to the event loop.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The event demultiplexer also fulfills the I/O request for fileA.txt and adds the result and the callback to the event loop.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The event loop runs the result through the callback for fileA, which emits a &lt;code class=&quot;language-text&quot;&gt;fileread&lt;/code&gt; event (line 11) AND a &lt;code class=&quot;language-text&quot;&gt;found&lt;/code&gt; event (line 16). The EventEmitter adds the &lt;code class=&quot;language-text&quot;&gt;fileread&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;found&lt;/code&gt; handlers to the event loop.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The event loop is busily processing all of these events in the order of arrival:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;run the listener callback for the &lt;code class=&quot;language-text&quot;&gt;error&lt;/code&gt; event (fileC)&lt;/li&gt;
&lt;li&gt;run the listener callback for the &lt;code class=&quot;language-text&quot;&gt;fileread&lt;/code&gt; event (fileB)&lt;/li&gt;
&lt;li&gt;run the listener callback for the &lt;code class=&quot;language-text&quot;&gt;fileread&lt;/code&gt; event (fileA)&lt;/li&gt;
&lt;li&gt;FINALLY — run the listener callback for the &lt;code class=&quot;language-text&quot;&gt;found&lt;/code&gt; event (fileA)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The result of running this script on the command line:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ node --use_strict events.js
Error emitted: ENOENT: no such file or directory, open &apos;fileC.md&apos;
fileB.json was read
fileA.txt was read
Matched hello blah in file fileA.txt&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;em&gt;Side note: set the flag &lt;code class=&quot;language-text&quot;&gt;--use-strict&lt;/code&gt; to run scripts using ES6 syntax&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Why did the files process in what seems to be reverse order? The event demultiplexer adds work to the event loop as it fulfills I/O requests. When &lt;code class=&quot;language-text&quot;&gt;readfile()&lt;/code&gt; is given three files — a file with content (fileA), an empty file (fileB), and a non-existent file (fileC) — it is reasonable to assume that the I/O request for a non-existent file will return first, as there is no file to read. It is also reasonable that an empty file will  return next, as there is very little work to be done reading an empty file. Finally, the I/O request for the file with content returns — it requires more work to read a file with content than an empty file.&lt;/p&gt;
&lt;p&gt;For more about the event emitter pattern in Node, check out &lt;a href=&quot;https://www.amazon.com/Node-js-Design-Patterns-Mario-Casciaro/dp/1785885588/ref=sr_1_1/161-7210115-5247461?ie=UTF8&amp;#x26;qid=1476284148&amp;#x26;sr=8-1&amp;#x26;keywords=node.js+design+patterns&quot;&gt;Node.js Design Patterns&lt;/a&gt; by Mario Casciaro and Luciano Mammino.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[callbacks and the event loop]]></title><description><![CDATA[When I started writing javascript in earnest a couple of years ago, I was stuck in a very procedural way of thinking — all of my functions…]]></description><link>http://katieleonard.ca/blog/2016/2016-10-12-clarified-callbacks/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2016/2016-10-12-clarified-callbacks/</guid><pubDate>Wed, 12 Oct 2016 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;When I started writing javascript in earnest a couple of years ago, I was stuck in a very procedural way of thinking — all of my functions executed synchronously. If you replaced &lt;code class=&quot;language-text&quot;&gt;function&lt;/code&gt; with &lt;code class=&quot;language-text&quot;&gt;def&lt;/code&gt; and removed all &lt;code class=&quot;language-text&quot;&gt;var&lt;/code&gt; keywords, you would be reading Ruby (true story: yesterday I was debugging an issue with a React module and put in a &lt;code class=&quot;language-text&quot;&gt;binding.pry&lt;/code&gt; instead of &lt;code class=&quot;language-text&quot;&gt;debugger&lt;/code&gt; :facepalm: Old habits die hard).&lt;/p&gt;
&lt;p&gt;Last year, I joined a team that writes javascript in the Node.js style, using callbacks for flow control. While I became familiar with the pattern pretty quickly, the whys and wherefores were missing from my understanding. Today I am filling in the gaps by reading &lt;a href=&quot;https://www.amazon.com/Node-js-Design-Patterns-Mario-Casciaro/dp/1785885588/ref=sr_1_1/161-7210115-5247461?ie=UTF8&amp;#x26;qid=1476284148&amp;#x26;sr=8-1&amp;#x26;keywords=node.js+design+patterns&quot;&gt;Node.js Design Patterns&lt;/a&gt; by Mario Casciaro and Luciano Mammino.&lt;!--more--&gt;&lt;/p&gt;
&lt;h3&gt;The Event Loop&lt;/h3&gt;
&lt;p&gt;The first step to understanding asynchronous javascript is to understand the event loop. It is a single thread that processes one message at a time, as they appear in the FIFO event queue.&lt;/p&gt;
&lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/f78644d8afea9f6e939244ce846a5d10/7131f/event-loop.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 62.65822784810127%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAANCAIAAAAmMtkJAAAACXBIWXMAAAsTAAALEwEAmpwYAAACH0lEQVQoz02S647aQAyFef/3qfoGi1btHwJsbpCwLCEhyUwmc83c7IqwrXo0P8aWPtk6PhsAEEKoVXIV55wQQilt27auq/pyJbOmdBq7LzlcFbnLsbFqPh4/NgAYY8T/5L1/dULwPkSvGdI8ktwMFYgGVQeqxyirqt4gQIzhhVlrnXNSqcejb5qGkHEWmp23l98/267nyiAtcTrDfEXdns/nDTMw6UA0iiVIzixr9NSRsZ/nmTGmpJxm0d7q9rTj9wz4DcUd1IBBPOETxcvo6xmuDLUSKBrUPQT72iWEqDg12Q/dZuAXNATMFDVFxHWyR91Sn35K78f+Yccq8A6iX1nw3mtjbERYa+cDm0XbPZRSaZpuEHGitK0/T+dTWRZV/TleDqorULVoyHoCsZryxBljZVGkaVoUxfv7+xO+3ZpjmmZZdjqdiqLMk1/jvUL18JpJpbUx2izOhwhICNnv97vdLkmSt7e3F3z7OB4+joc8S9PjMSvK7tEvi9VacyH6+5X3VzF+BU2HYTgcDkmy2+/32+32CQ/DcP7qqq/+0gxVM9zbh5ISEWMI1vmwCMc7WBhayuhQlGWeZd9rA4BUSixxXkAuUbmnK9Z+ux1jtNb9y4/WZlmstRYAkiTZvCIVvHd2kYLbxVijord/n8PoXp/onTVKK0kpdc7lef6cHMIzYQDgnPNucYY7zZxiTs9Oc8VGKydnxFoyb4117nXnPwop2ySRZoD/AAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;event loop&quot; title=&quot;event loop&quot; src=&quot;/static/f78644d8afea9f6e939244ce846a5d10/f058b/event-loop.png&quot; srcset=&quot;/static/f78644d8afea9f6e939244ce846a5d10/c26ae/event-loop.png 158w,
/static/f78644d8afea9f6e939244ce846a5d10/6bdcf/event-loop.png 315w,
/static/f78644d8afea9f6e939244ce846a5d10/f058b/event-loop.png 630w,
/static/f78644d8afea9f6e939244ce846a5d10/7131f/event-loop.png 710w&quot; sizes=&quot;(max-width: 630px) 100vw, 630px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
&lt;p&gt;&lt;em&gt;image credit: Mario Casciaro and Luciano Mammino from Node.js Design Patterns. Colour notations are mine.&lt;/em&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;An I/O request is sent to the event demultiplexer.&lt;/li&gt;
&lt;li&gt;The event demultiplexer queues the I/O instructions along with the context and a callback function that contains the instructions for what do to with the result once it is received.&lt;/li&gt;
&lt;li&gt;When the I/O order is filled, the event demultiplexer pops an event on to the event queue, with the filled I/O request, and the callback handler.&lt;/li&gt;
&lt;li&gt;The event loop pulls the event off of the event queue and applies the result to the callback function.&lt;/li&gt;
&lt;li&gt;The event loop either sends the result of the callback operation to the application, or generates more I/O work for the event demultiplexer.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;When I check my email in the morning, I go through a similar process:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;My inbox is the event demultiplexer, where requests for resources are made.&lt;/li&gt;
&lt;li&gt;I (as the event loop) process emails from in the queue from oldest to newest, and I only process one at at time.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;For each message I read the context and perform one of two actions (callback):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Process the message and return to the queue to pick up another message.&lt;/li&gt;
&lt;li&gt;Add a new action to my todo list event queue along with the a reminder to attach the result of the new action to the email when I respond (callback).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;When I am finished with my email inbox I start on my todo list, performing the actions required and responding to the email. Sometimes the action will generate additional actions, which I append to the end of my todo list. While the idea of an infinite todo list is a little disheartening to a human, this is how the V8 javascript engine was designed: it performs the work with maximum efficiency, and can do so with only a single thread.&lt;/p&gt;
&lt;h3&gt;The difference between synchronous and asynchronous javascript&lt;/h3&gt;
&lt;p&gt;Synchronous javascript can be easily identified by the use of a &lt;code class=&quot;language-text&quot;&gt;return&lt;/code&gt; statement, which returns control back to the caller.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;introduction&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;firstName&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; lastName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Hello, my name is &apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; firstName &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos; &apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; lastName
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token function&quot;&gt;introduction&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Keighty&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Leonard&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// &quot;hello! my name is Keighty Leonard&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Asynchronous javascript uses a ‘continuous passing pattern’, where the result of a function is passed to a handler for further processing.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;createEmailAddress&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;firstName&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; lastName&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; callback&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// create asynchronous call&lt;/span&gt;
  console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;before the async&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;setTimeout&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// do some work&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; email &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; firstName&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toLowerCase&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;.&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; lastName&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toLowerCase&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;@example.com&apos;&lt;/span&gt;
    console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;during the async&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// pass the result of the work to the callback&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;callback&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;email&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2000&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;after the async&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;cb&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;result&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token function&quot;&gt;createEmailAddress&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Keighty&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Leonard&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; cb&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// &gt; before the async&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// &gt; after the async&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// &gt; during the async&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// &gt; keighty.leonard@example.com&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;createEmailAddress&lt;/code&gt; is called. When execution reaches the setTimeout function, and the 2000ms have elapsed, the callback passed to setTimeout is placed in the event queue, awaiting its turn for execution. The thread is release and does not have to wait for the setTimeout period to elapse before continuing execution — it continues with the second console statement (‘after the async’). When the setTimeout callback is finally processed, the &lt;code class=&quot;language-text&quot;&gt;firstName&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;lastName&lt;/code&gt; variables are still accessible because they exist in the function closure.&lt;/p&gt;
&lt;p&gt;Javascript has many features that make the continuous passing pattern easy:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Closures allow you to access the environment on which a function was created, no matter when the callback is invoked.&lt;/li&gt;
&lt;li&gt;Functions are first class data types, meaning they can be assigned to variables, passed as parameters, and stored in data structures.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;More on the event loop and event-emitter observer pattern to come!&lt;/p&gt;</content:encoded></item><item><title><![CDATA[git squash to speed up your workflow]]></title><description><![CDATA[I am a big fan of work-in-progress (WIP) commits. When I am working through a prototype or a spike, and need to do some experimentation with…]]></description><link>http://katieleonard.ca/blog/2016/2016-09-12-git-squash-to-speed-up-your-workflow/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2016/2016-09-12-git-squash-to-speed-up-your-workflow/</guid><pubDate>Mon, 12 Sep 2016 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I am a big fan of work-in-progress (WIP) commits. When I am working through a prototype or a spike, and need to do some experimentation with the code, I use WIP commits like they are save points in a game. &lt;!--more--&gt;These points act like milestones, and allow me to keep working with the confidence that I can always go back to an earlier working state. I use these aliases for the job:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# in ~/.bashrc&lt;/span&gt;
$ &lt;span class=&quot;token builtin class-name&quot;&gt;alias&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;wip&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;git commit -am &apos;WIP&apos;&quot;&lt;/span&gt;
$ &lt;span class=&quot;token builtin class-name&quot;&gt;alias&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;popwip&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;git reset --soft head~1; git reset head .&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;When I get the work into a good state, I &lt;code class=&quot;language-text&quot;&gt;wip&lt;/code&gt; it (I may even sing 🎶 &lt;a href=&quot;https://www.youtube.com/watch?v=IIEVqFB4WUo&quot;&gt;&lt;em&gt;When a problem comes along… you must whip it!&lt;/em&gt;&lt;/a&gt; 🎶). If I want to grab the last WIP commit from the branch, I &lt;code class=&quot;language-text&quot;&gt;popwip&lt;/code&gt; to pop the last commit off the stack and put the last bunch of changes back into my working directory.&lt;/p&gt;
&lt;p&gt;However, when I have been prototyping for a while, making &lt;code class=&quot;language-text&quot;&gt;wip&lt;/code&gt; commits as I go, popping a bunch of commits off the stack gets a little unwieldy. Until now I used an interactive rebase to rewrite my branch’s commit history. For example:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; log --pretty&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;format:&lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;&quot;%h %ad &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; %s%d &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;%an&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;&quot; --graph --date&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;short&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/c5b4313fa8a68216c2b73af56c8edeb3/5a190/githist.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 51.26582278481012%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAIAAAA7N+mxAAAACXBIWXMAAAsTAAALEwEAmpwYAAAB90lEQVQozyXQyW7bMAAEUNqWbEmkNoqyRIrUQlm2vGoxndZ1jCQIkhyCFkhSoEAPRS8F8v9fUDh5pzkM5jDg/v7+5eXl4fHx1+v3f6/X72/n30/d+8/zn2d1d/1l3ez7w3HT9ExkWZ6nWU75JXwCeVFsNxtZ1W83yyqLvDjLyoWsW05QFQDuDnZ0sI0H+2QAAEhssI7A8BI/JEmy3e1m8/p02P44zW/b7EbVz6fVzTpMKdkI+7oyuxLvpeu4rqROk1phSDzPIwEGcTKdhtP4gnEWFbG7yYOEQHOia/pEH40MfQCN0VgfYqg5pmboQx+NEYSmaQLG2XK5nH1Y1DXjYrZYSllWVVWv1uc5eqonD2v771d0zLVzqd9W+rEYY99zHBdMWXQ8fuv7/nB1tVeqKIqu7Zpmt7nYzqVQ+31dL1JijLXhSNONyXisa5o2GmkaQBjlWZ5mWVmWUkoSBAljjDIaUyF4wvl8XkVR5GNCCKGUcsGDIEgFF4JfDpOy8H3fcRyMMYTQdV1oWQhCx7EtyzJNE+MgCAIf+57vObaN0KVjWRagMU9FSikNwzCO48+JMAwJIb7nBRgzxiCEto1M03Bd17aRj32EoO95QIhMKXU4HNq2UUpJKbu+b5tdXa/Wq1XXtUqpLE0ZpYSQOI6F4AghXdMNw/gPPdxD3aZD9QIAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;githist&quot; title=&quot;githist&quot; src=&quot;/static/c5b4313fa8a68216c2b73af56c8edeb3/f058b/githist.png&quot; srcset=&quot;/static/c5b4313fa8a68216c2b73af56c8edeb3/c26ae/githist.png 158w,
/static/c5b4313fa8a68216c2b73af56c8edeb3/6bdcf/githist.png 315w,
/static/c5b4313fa8a68216c2b73af56c8edeb3/f058b/githist.png 630w,
/static/c5b4313fa8a68216c2b73af56c8edeb3/5a190/githist.png 800w&quot; sizes=&quot;(max-width: 630px) 100vw, 630px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
&lt;p&gt;For this git history, I would rebase on sha 83bfc47:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; rebase -i 83bfc47

pick 540c0fe WIP
pick 8af4cfe WIP
pick 50bd7db WIP
pick f90410b WIP

&lt;span class=&quot;token comment&quot;&gt;# Rebase 83bfc47..f90410b onto 83bfc47&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;#&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# MOAR git-structions below...&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I would proceed to &lt;code class=&quot;language-text&quot;&gt;reword&lt;/code&gt; the first and &lt;code class=&quot;language-text&quot;&gt;fixup&lt;/code&gt; the rest, writing a thoughtful and all-encompassing commit message to convey the intention behind this chunk of work. Then I discovered &lt;code class=&quot;language-text&quot;&gt;git merge --squash&lt;/code&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; checkout master
Switched to branch &lt;span class=&quot;token string&quot;&gt;&apos;master&apos;&lt;/span&gt;
Your branch is up-to-date with &lt;span class=&quot;token string&quot;&gt;&apos;origin/master&apos;&lt;/span&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;.&lt;/span&gt;

$ &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; merge --squash test_branch
Updating 83bfc47&lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;f90410b
Fast-forward
Squash commit -- not updating HEAD
 routes/performance.js                          &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt; +++
 routes/performer.js                            &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt; +++
 routes/user.js                                 &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt; ++
 src/app.js                                     &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt; +++
 src/components/performance-frame.jsx           &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt; +++
 src/containers/filterable-performance-grid.jsx &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt; +++
 &lt;span class=&quot;token number&quot;&gt;6&lt;/span&gt; files changed, &lt;span class=&quot;token number&quot;&gt;17&lt;/span&gt; insertions&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;+&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

$ &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; status
On branch master
Your branch is up-to-date with &lt;span class=&quot;token string&quot;&gt;&apos;origin/master&apos;&lt;/span&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;.&lt;/span&gt;
Changes to be committed:
  &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;use &lt;span class=&quot;token string&quot;&gt;&quot;git reset HEAD &amp;lt;file&gt;...&quot;&lt;/span&gt; to unstage&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

	modified:   routes/performance.js
	modified:   routes/performer.js
	modified:   routes/user.js
	modified:   src/app.js
	modified:   src/components/performance-frame.jsx
	modified:   src/containers/filterable-performance-grid.jsx&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;All of the changes I have made on that branch since it diverged from master have been added to the index. I am free to either chunk up the changes into different commits (with commit messages that are more descriptive than WIP), or add them all to a single commit.&lt;/p&gt;
&lt;p&gt;GOODBYE &lt;code class=&quot;language-text&quot;&gt;rebase -i&lt;/code&gt;! &lt;code class=&quot;language-text&quot;&gt;Hello merge --squash&lt;/code&gt;!&lt;/p&gt;</content:encoded></item><item><title><![CDATA[importing and exporting: modular React]]></title><description><![CDATA[While working on rewriting my side-project (VirtualPlaybill) in React, I got hung up on a very basic plumbing concept: named exports.  With…]]></description><link>http://katieleonard.ca/blog/2016/2016-08-18-importing-and-exporting-modular-react/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2016/2016-08-18-importing-and-exporting-modular-react/</guid><pubDate>Thu, 18 Aug 2016 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;While working on rewriting my side-project (VirtualPlaybill) in React, I got hung up on a very basic plumbing concept: named exports. &lt;!--more--&gt;&lt;/p&gt;
&lt;p&gt;With ES5 you can export in three ways and import in one:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// EXPORT STYLE 1&lt;/span&gt;
module&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;exports &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token function-variable function&quot;&gt;crunchy&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;CRUNCHY!&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token function-variable function&quot;&gt;bacon&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;BACON!&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// EXPORT STYLE 2&lt;/span&gt;
exports&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function-variable function&quot;&gt;crunchy&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;CRUNCHY!&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
exports&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function-variable function&quot;&gt;bacon&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;BACON!&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// EXPORT STYLE 3 (and my personal favourite)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; breakfast &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token function-variable function&quot;&gt;crunchy&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;CRUNCHY!&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token function-variable function&quot;&gt;bacon&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;BACON!&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
module&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;exports &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; breakfast&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;An export is a meaningful bundle of code. Importing takes a single form, providing a handle to the exported bundle:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// IMPORT&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; breakfast &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;breakfast.js&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

breakfast&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;crunchy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// CRUNCHY!&lt;/span&gt;
breakfast&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;bacon&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// BACON!&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In ES6 there is a lot more flexibility: exports can be named and imports can take many forms.&lt;/p&gt;
&lt;h4&gt;Named exports&lt;/h4&gt;
&lt;p&gt;Importing a named export allows you to grab only the functions you need from a module, leaving the rest behind. Use curly braces to import a named export:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;//-----test.js-----//&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;crunchy&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;CRUNCHY!&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;bacon&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;BACON!&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// IMPORT BY NAME&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//-----main.js-----//&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; crunchy &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;./test&apos;&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;crunchy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// CRUNCHY!&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;bacon&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Uncaught ReferenceError: bacon is not defined(…)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h4&gt;Default exports&lt;/h4&gt;
&lt;p&gt;In addition to named exports, you can specify one &lt;code class=&quot;language-text&quot;&gt;default&lt;/code&gt; export per file. Simply importing that file provides a reference to the default export:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;//-----test.js-----//&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;crunchy&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;CRUNCHY!&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;default&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;bacon&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;BACON!&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// IMPORT BY DEFAULT&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//-----main.js-----//&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; myFunc &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;./test&apos;&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;myFunc&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// BACON!&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;You can also import both default and named exports at the same time:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; myFunc&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; crunchy &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;./test&apos;&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;crunchy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// CRUNCHY!&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;myFunc&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// BACON!&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;For even more import options, checkout the section on imports from the &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import&quot;&gt;MDN docs&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; defaultMember &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;module-name&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; name &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;module-name&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; member &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;module-name&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; member &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; alias &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;module-name&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; member1 &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; member2 &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;module-name&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; member1 &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; member2 &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; alias2 &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;module-name&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; defaultMember&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; member &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;module-name&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; defaultMember&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; name &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;module-name&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;module-name&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;name&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Name of the object that will receive the imported values.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;member, memberN&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Name of the exported members to be imported.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;defaultMember&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Name of the exported default to be imported.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;alias, aliasN&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Name of the object that will receive the imported property&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;module-name&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The name of the module to import. This is a file name.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h4&gt;What you CAN’T do…&lt;/h4&gt;
&lt;p&gt;… is use ES5 syntax and expect the import to know what you mean:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;//------my-component.js-------//&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;MyComponent&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;React&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Component&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;render&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;p&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt; is an awesome react component &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;p&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;default&lt;/span&gt; MyComponent

&lt;span class=&quot;token comment&quot;&gt;//------main.js-------//&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; MyComponent &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;./my-component&apos;&lt;/span&gt;
console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;MyComponent&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// undefined&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I was trying to write ES5 in ES6! Without an explicit &lt;code class=&quot;language-text&quot;&gt;export&lt;/code&gt; in front of the class declaration, my default had no idea what I intended to export, so it did nothing. Adding &lt;code class=&quot;language-text&quot;&gt;export&lt;/code&gt; to the class definition, or even moving the whole &lt;code class=&quot;language-text&quot;&gt;export default&lt;/code&gt; to the class declaration does the job:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;//------my-component.js-------//&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;default&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;MyComponent&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;React&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Component&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;render&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;p&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt; is an awesome react component &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;p&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;//------main.js-------//&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; MyComponent &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;./my-component&apos;&lt;/span&gt;
console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;MyComponent&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// function MyComponent() {...}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Thanks to &lt;a href=&quot;http://stackoverflow.com/a/31853887&quot;&gt;this stackoverflow answer&lt;/a&gt; for pointing me in the right direction, and &lt;a href=&quot;http://exploringjs.com/es6/ch_modules.html&quot;&gt;exploringjs&lt;/a&gt; for even greater detail!&lt;/p&gt;</content:encoded></item><item><title><![CDATA[nested routes with expressjs]]></title><description><![CDATA[Whenever I need to build a quick web application I turn to ExpressJS. It is a fast, minimal, easy to configure web server that puts the E in…]]></description><link>http://katieleonard.ca/blog/2016/2016-04-12-nested-routes-with-expressjs/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2016/2016-04-12-nested-routes-with-expressjs/</guid><pubDate>Tue, 12 Apr 2016 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Whenever I need to build a quick web application I turn to &lt;a href=&quot;http://expressjs.com/&quot;&gt;ExpressJS&lt;/a&gt;. It is a fast, minimal, easy to configure web server that puts the &lt;strong&gt;E&lt;/strong&gt; in &lt;a href=&quot;http://mean.io/#!/&quot;&gt;MEAN&lt;/a&gt;). I wanted to build a REST API for a hobby app and found that the docs for how to nest routes are relatively few (see &lt;a href=&quot;http://codetunnel.io/an-intuitive-way-to-organize-your-expressjs-routes/&quot;&gt;blog&lt;/a&gt;, &lt;a href=&quot;http://stackoverflow.com/a/25305272/1279340&quot;&gt;stackoverflow answer&lt;/a&gt;). Combining these two resources, I learned a simple method for keeping your routes separate while creating a nested routing structure. &lt;!--more--&gt;&lt;/p&gt;
&lt;h2&gt;The Plan&lt;/h2&gt;
&lt;p&gt;I want to create routes that look like these:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;/foo&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;/foo/bar&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;/foo/42&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;/foo/42/baz&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;/foo/42/baz/123&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Using the &lt;a href=&quot;http://expressjs.com/en/starter/generator.html&quot;&gt;express-generator&lt;/a&gt; and a few simple commands, you can get your server up and running fast:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ npm install express-generator -g
$ express myapp
$ cd myapp
$ npm install
$ npm start&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;You will end up with a working directory that looks like this:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;├── app.js
├── bin
│   └── www
├── node_modules
│   ├── ...
├── package.json
├── public
│   ├── images
│   ├── javascripts
│   └── stylesheets
│       └── style.css
├── routes
│   ├── index.js
│   └── users.js
└── views
    ├── error.jade
    ├── index.jade
    └── layout.jade&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Go ahead and delete the &lt;code class=&quot;language-text&quot;&gt;/routes/users.js&lt;/code&gt; file and the following lines from &lt;code class=&quot;language-text&quot;&gt;app.js&lt;/code&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; users &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;./routes/users&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
app&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;/users&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; users&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Then create a new routes file named &lt;code class=&quot;language-text&quot;&gt;/routes/foo.js&lt;/code&gt; and and require it from your app server.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
app&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;/foo&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;./routes/foo&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;How to &lt;code class=&quot;language-text&quot;&gt;GET /foo&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Inside &lt;code class=&quot;language-text&quot;&gt;/routes/foo.js&lt;/code&gt;, you need to require the router module from ExpressJS, define a route on it, and export it back out.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; express &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;express&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; router &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; express&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Router&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// GET /foo&lt;/span&gt;
router&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;/&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;req&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; res&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; next&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  res&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;send&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;this is the index for foo&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

module&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;exports &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; router&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Everytime you change a route, you need to restart your server. Nevigating to &lt;a href=&quot;http://localhost:3000/foo&quot;&gt;localhost:3000/foo&lt;/a&gt; should display the message:&lt;/p&gt;
&lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 350px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/5f6275cbef652f5ed768476bd86600ec/13ae7/foo.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 32.911392405063296%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAHCAIAAACHqfpvAAAACXBIWXMAAAsTAAALEwEAmpwYAAABEklEQVQY032NW0vDQBCF8///jw/6IAjaEsWYpFa7m9tsNrs7e0nbdNtA8tBIpCgo+p2ZgRnOcIJ2fV/A3QMLtURgs+ZiDACqqoIKhBCoEBGllE3TcN4o9bkjBnV4na6vbt5ujdJlWaRJGsdxMs8kXC6fHiMhRNd1bdtKKbMsWyyWSZJSSgkhQS21Uo5lEL1E1rnWWUTknAvRaESlBKtrzvlut+v73nu/774JCNlUUK5eV2EYOuesUekqjeL4JXrevG/KssjLMqfUWDuO4zAM4xfDGBitEdEY46xVUqHW2+3WOeePx1PfHy+c/OEwZ+0vfUlmAAygKIq8yCkhwGpgQGnmvZ+m6Xw+T38T/Lr85/7x/AHtjn9/zlnmkgAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;foo&quot; title=&quot;foo&quot; src=&quot;/static/5f6275cbef652f5ed768476bd86600ec/13ae7/foo.png&quot; srcset=&quot;/static/5f6275cbef652f5ed768476bd86600ec/c26ae/foo.png 158w,
/static/5f6275cbef652f5ed768476bd86600ec/6bdcf/foo.png 315w,
/static/5f6275cbef652f5ed768476bd86600ec/13ae7/foo.png 350w&quot; sizes=&quot;(max-width: 350px) 100vw, 350px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
&lt;h2&gt;How to &lt;code class=&quot;language-text&quot;&gt;GET /foo/bar&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Create simple nested routes by requiring the child route file from the parent route file.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; express &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;express&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; router &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; express&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Router&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; bar &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;./bar&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// GET /foo&lt;/span&gt;
router&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;/&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;req&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; res&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; next&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  res&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;send&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;this is the index for foo&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// GET /foo/bar&lt;/span&gt;
router&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;/bar&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; bar&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// tell the router to use bar.js for child routes&lt;/span&gt;

module&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;exports &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; router&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Create a new routes file named &lt;code class=&quot;language-text&quot;&gt;/routes/bar.js&lt;/code&gt; and define a root route the same way you did for &lt;code class=&quot;language-text&quot;&gt;/routes/foo.js&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; express &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;express&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; router &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; express&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Router&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// GET /foo/bar&lt;/span&gt;
router&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;/&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;req&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; res&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; next&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  res&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;send&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;this is the index for bar&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

module&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;exports &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; router&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Bounce your server again and navigate to &lt;a href=&quot;http://localhost:3000/foo/bar&quot;&gt;localhost:3000/foo/bar&lt;/a&gt;&lt;/p&gt;
&lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 350px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/2a83ab0a703b654074d71697d8efa1b3/13ae7/foobar.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 34.810126582278485%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAHCAIAAACHqfpvAAAACXBIWXMAAAsTAAALEwEAmpwYAAABC0lEQVQY04XPQW6DMBAFUO5/mi56gUhVm0BKMDQJtokpMcx4jIxZlIRsoCJSpG7avs0faRZfP6BD7lVS1PERhDW2aRpABGgAoL5DAEAgImOMQUNE9iHQqxezfX47PK3EKzW03+9ZwhLG0uxjG0VR+J7EuyzNOu+ttUqpzXqTZVlRFFLKID0eT1UDmsSBCymdc4iotS7LcqlFrJsaAJZeMn3fd65zznV3QbhZS8FVeQqjcBfH1trPUrE0TXYxS5gQIuc550JwznnufX+5XIaHgIjatkXEtrXLKkNkl33e97fbeL1ex3Fc4n4Mw/D1Q3A+a61rrZeQUp6rSuu6VAoB53mepmn+XfDHb/rPN/nDfiMkpXf5AAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;foobar&quot; title=&quot;foobar&quot; src=&quot;/static/2a83ab0a703b654074d71697d8efa1b3/13ae7/foobar.png&quot; srcset=&quot;/static/2a83ab0a703b654074d71697d8efa1b3/c26ae/foobar.png 158w,
/static/2a83ab0a703b654074d71697d8efa1b3/6bdcf/foobar.png 315w,
/static/2a83ab0a703b654074d71697d8efa1b3/13ae7/foobar.png 350w&quot; sizes=&quot;(max-width: 350px) 100vw, 350px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
&lt;h2&gt;How to &lt;code class=&quot;language-text&quot;&gt;GET /foo/42&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Expecting a parameter? No problem! access URL params directly from the request object: &lt;code class=&quot;language-text&quot;&gt;req.params.nameOfParam&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// GET /foo/42&lt;/span&gt;
router&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;/:number&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;req&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; res&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; next&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  res&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;send&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;this is foo #&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; req&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;params&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;number&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

module&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;exports &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; router&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Navigate to &lt;a href=&quot;http://localhost:3000/foo/42&quot;&gt;localhost:3000/foo/42&lt;/a&gt; to see the result.&lt;/p&gt;
&lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 350px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/1812bbca97aa9645dd3c345dc93e1b2d/13ae7/fooNumber.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 32.911392405063296%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAHCAIAAACHqfpvAAAACXBIWXMAAAsTAAALEwEAmpwYAAAA+ElEQVQY05WOTW6DMBCFff+7dNNuukVCSiFgQhSCoTaIOB7/FXIAsKkMzaK79pNG82ZGmvfQSMubOJ1FZZQGACWlkj8AwNakUkprrVS47FqbUEgdXs/Xl7f63YAmpC7wKc9zjIs8x3EcZ2mefCSs66bHJIRo2zZJ0sulYoxRSlHPJef6RgdCiLVW6+B9FwIA9DZIAGOMDXxN4wgixAnmWqH6WjFGcYGjKLLWGinKskyPR5xldV1T2pKm+Wwb1nV937tl8d47590GstaY7c/+b5wCj42nmKbncvwN6vuODwOjXUMazu/ruq7er38DzfPsnFuWZU/i/8M3rqF/E4UQRzQAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;fooNumber&quot; title=&quot;fooNumber&quot; src=&quot;/static/1812bbca97aa9645dd3c345dc93e1b2d/13ae7/fooNumber.png&quot; srcset=&quot;/static/1812bbca97aa9645dd3c345dc93e1b2d/c26ae/fooNumber.png 158w,
/static/1812bbca97aa9645dd3c345dc93e1b2d/6bdcf/fooNumber.png 315w,
/static/1812bbca97aa9645dd3c345dc93e1b2d/13ae7/fooNumber.png 350w&quot; sizes=&quot;(max-width: 350px) 100vw, 350px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
&lt;h2&gt;How to &lt;code class=&quot;language-text&quot;&gt;GET /foo/42/baz&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Getting a child route from a parameterized parent is where I was getting confused. It turns out that you need to configure the router a little differently when you are passing params through.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; baz &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;./baz&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// GET /foo/42/baz&lt;/span&gt;
router&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;/:number/baz&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; baz&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

module&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;exports &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; router&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;You need to pass an options object to &lt;code class=&quot;language-text&quot;&gt;express.Router&lt;/code&gt; to merge the params from any parent route:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; express &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;express&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; router &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; express&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Router&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token literal-property property&quot;&gt;mergeParams&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// don&apos;t forget the parent params!&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// GET /foo/42/baz&lt;/span&gt;
router&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;/&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;req&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; res&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; next&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// the param name is from the parent as well&lt;/span&gt;
  res&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;send&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;this is the baz for foo#&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; req&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;params&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;number&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

module&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;exports &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; router&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Navigate to &lt;a href=&quot;http://localhost:3000/foo/42/baz&quot;&gt;localhost:3000/foo/42/baz&lt;/a&gt; to enjoy your success.&lt;/p&gt;
&lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 350px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/bc93f0195567d13178466c55910e9c3b/13ae7/fooNumberBaz.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 32.911392405063296%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAHCAIAAACHqfpvAAAACXBIWXMAAAsTAAALEwEAmpwYAAABA0lEQVQY04XPTU7DMBCGYd//Lmxgw7ZSJdSkdoNp/hy7cRtie2ba5ACtCUoDEmzgkSx9s3pldtGvpz6TfY4BnHPB++C/OOe+pw93ywAAwPmx8PIoi4en8hkdVFW5ExnnXIgd52K9XqcJT9NtmiRSSud80zSbTbLf58YYrTVrO991cNLHqqqICGBuv/e9cw7uh/duySJSCKHrOu/9HIfAyiI3RotMrFYrQiJw8k2m2+1O8LIstVZlXTdKWXtUSql6DkzTFO8YESJACPNnEBAQiYjOZ0IchmGcDYtxHC+/Mdu2tj1obZRqDsZYaw+6KfKirusY4/Qndr1ebz/EW4zLiPHjP5+SiXu7e+oLEwAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;fooNumberBaz&quot; title=&quot;fooNumberBaz&quot; src=&quot;/static/bc93f0195567d13178466c55910e9c3b/13ae7/fooNumberBaz.png&quot; srcset=&quot;/static/bc93f0195567d13178466c55910e9c3b/c26ae/fooNumberBaz.png 158w,
/static/bc93f0195567d13178466c55910e9c3b/6bdcf/fooNumberBaz.png 315w,
/static/bc93f0195567d13178466c55910e9c3b/13ae7/fooNumberBaz.png 350w&quot; sizes=&quot;(max-width: 350px) 100vw, 350px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
&lt;h2&gt;How to &lt;code class=&quot;language-text&quot;&gt;GET /foo/42/baz/123&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Parameterizing a child route is the same process as for the parent route:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; express &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;express&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; router &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; express&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Router&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token literal-property property&quot;&gt;mergeParams&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// GET /foo/42/baz&lt;/span&gt;
router&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;/&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;req&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; res&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; next&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  res&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;send&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;this is the baz for foo#&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; req&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;params&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;number&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// GET /foo/42/baz/123&lt;/span&gt;
router&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;/:id&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;req&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; res&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; next&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  res&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;send&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;baz #&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; req&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;params&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; ‘ &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; foo #’ &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; req&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;params&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;number&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

module&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;exports &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; router&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Navigate to &lt;a href=&quot;http://localhost:3000/foo/42/baz/123&quot;&gt;localhost:3000/foo/42/baz/123&lt;/a&gt; to enjoy your success.&lt;/p&gt;
&lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 350px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/f0dc4adb1b77b2f206bc3edc9dc9e3f8/13ae7/fooNumberBazNumber.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 32.911392405063296%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAHCAIAAACHqfpvAAAACXBIWXMAAAsTAAALEwEAmpwYAAABCUlEQVQY043PwXKCMBQFUP7/Vzr1A7R7hYoIElIJ5IGEvIQQ9iqBDlqnu07P6t7NffO8vqQGaYZUaaWU0kp3eqFelqx/dV1nXrz2472mq7dsBRdelpycSHQ4HKIoOib+duvvPuNjvN+HAKCUqi91GIZJcqqqinPusbqpG9WCYIw9txFl20opJaJEVLgEXA72puu6+kEIgYhe4PvAy5Skm82aczCmz0jqB0Hg75I4zs/njGaUfhUFy/OcpAQAhGgAKuecZ4xBiVLKVrZaa2vt86thGKy1w8tPtoO1/aMt1ctzJhpRsKIGKDmURZkRohTO8zxN0/wn73q9OufGh/v9frvdxnF0zk3/8A23LHuUB4WjIgAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;fooNumberBazNumber&quot; title=&quot;fooNumberBazNumber&quot; src=&quot;/static/f0dc4adb1b77b2f206bc3edc9dc9e3f8/13ae7/fooNumberBazNumber.png&quot; srcset=&quot;/static/f0dc4adb1b77b2f206bc3edc9dc9e3f8/c26ae/fooNumberBazNumber.png 158w,
/static/f0dc4adb1b77b2f206bc3edc9dc9e3f8/6bdcf/fooNumberBazNumber.png 315w,
/static/f0dc4adb1b77b2f206bc3edc9dc9e3f8/13ae7/fooNumberBazNumber.png 350w&quot; sizes=&quot;(max-width: 350px) 100vw, 350px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
&lt;p&gt;TADA! a model of nested routes that you can apply to any application.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[preflight check with CORS]]></title><description><![CDATA[Modern web applications can draw resources from anywhere on the web. Fonts, JavaScript libraries, images, and other data can be fetched from…]]></description><link>http://katieleonard.ca/blog/2016/2016-03-29-preflight-check-with-cors/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2016/2016-03-29-preflight-check-with-cors/</guid><pubDate>Tue, 29 Mar 2016 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Modern web applications can draw resources from anywhere on the web. Fonts, JavaScript libraries, images, and other data can be fetched from CDNs, Amazon, IMDB, or anywhere else that provides a public API. Early browsers restricted web applications to same-origin requests, which prevented the sharing of resources between applications, but also ensured that data from one application could not be tampered with by another. The thinkers at the W3C came up with a means of communicating safe cross-origin requests that would allow even destructive remote actions to be performed, as long as the server consented to receive the request. Enter CORS, and preflighting.&lt;/p&gt;
&lt;!--more--&gt;
&lt;h3&gt;What is CORS?&lt;/h3&gt;
&lt;p&gt;Cross-Origin Resource Sharing occurs when JavaScript on a web page requests data from (or sends data to) a location on a different host. Any website that embeds a video from YouTube, uses a custom font, or posts to social media on your behalf, is making a CORS request. CORS is a &lt;a href=&quot;https://www.w3.org/TR/cors/&quot;&gt;set of web standards&lt;/a&gt; developed to enable safe cross-domain communication.&lt;/p&gt;
&lt;h3&gt;What is preflighting?&lt;/h3&gt;
&lt;p&gt;CORS functions through the specification of new HTTP headers that allow servers to describe the origin and nature of the request. For each outgoing request to a different domain, the browser will look at the headers to determine if the request that looks like it will affect data on the receiving server. Any simple request that uses one of the common HTTP verbs and a basic Content-Type are allowed to pass without further comment. But if the request has different header values, the browser checks with the server first to make sure the request is expected. This is called a pre-flight check.&lt;/p&gt;
&lt;h3&gt;What does a simple CORS request look like?&lt;/h3&gt;
&lt;p&gt;For simple requests (no pre-flight check), the method must be one of:
- GET
- HEAD
- POST&lt;/p&gt;
&lt;p&gt;The only extra headers allowed are:
- Accept
- Accept-Language
- Content-Language
- Content-Type&lt;/p&gt;
&lt;p&gt;For the Content-Type header, the only allowed values are:
- application/x-www-form-urlencoded
- multipart/form-data
- text/plain&lt;/p&gt;
&lt;p&gt;XMLHttpRequests (aka XHRs or ajax) use CORS to mitigate the risks of pulling or pushing sensitive data across domains. For example:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; body &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;very safe, ordinary text content&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; url &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;http://api.example.com&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; request &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;XMLHttpRequest&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;POST&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; url&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;setRequestHeader&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Content-Type&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;text/plain&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;send&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 311px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/52c8d3d8b3f32fb0cc6b827a852bf974/ffa0f/cors-without-preflight.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 98.73417721518987%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAIAAAAC64paAAAACXBIWXMAAAsTAAALEwEAmpwYAAACvklEQVQ4y52Ty0+rQBTG/f93brozTdzpNSyMGt3YaloJBErLm6IVKS1loMDwfg3c3E7lXpOu7m9xcpLJB+eb881Z13UIoTRNsyxL07T8pm3b/qjruqIoEEJN03T/cNZ1nW3bBEEMh8PBYDAej8/Pz4fD4d3d3c3NzcvLC0EQ9/f3g8Hg4uLi6urq+vr68vISAHAUV1Xluq7v+57nxXEcBEEYhq7rbjYbCGFRFJ7n+b6vaZrjOK7rKooSx/EfcdM0+/0eQhjHcZIktm0jhLpTlGUJIcQGHcf5I66qyrIsiqIYhlFVdTqdYpNd12HbfQMhlCSJYRhRFEmSPI6t6/rr6+vowPPzc5Zl9TfVgbIs67qOoogkyfF4PBqNKIr667koivV6bZomAABC6Hnedrvd7Xb7/T4IAlw1TYuiyPf9LMuwtbPeEgDAsixFUURRXK1WDMMsl0tJkliW5ThOURSapvFvejt/xY7j2LZtGIYsy5ZlaZpmGIZpmqqqCoKgqup2u0UIZVl2Qrzb7VzXxZeZ5zmEMIoi3DdNk2XZer2u6zpN09Pi1WrF87wkSX2VZXk+n7+/v7Msy/N8VVVJkpwQx3FcFAW+4bqu8zxP07QoirIs8zzHtW3b055N05xOp6Io8jyvaRrLspPJxHVd/JUkScqyBABIktRv/ihGCOE1+L4PIcRNGIZRFCUH4gMAAE3TfohxN5/PJ5MJwzCz2YymaUEQKIqSJGk2m3EcJwjC29sbx3H4SRzHRgiFYZjnua7rAADXdYuiqL7pXyhOmOd5OEVBEByzvdlsaJpeLBbL5ZIkyT7bPXi0OI51XV8sFqqqHuPZtq2iKI+Pj09PT6PR6Pb2FgCQpikAANv2fR8n9PPzkyCIXwceHh5+ZBuP9/HxoSiKYRiCICiKIkmSLMt4/wzD4P3Lsvz19fVjVf/Bb1O8SREo9/UfAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;cors without preflight&quot; title=&quot;cors without preflight&quot; src=&quot;/static/52c8d3d8b3f32fb0cc6b827a852bf974/ffa0f/cors-without-preflight.png&quot; srcset=&quot;/static/52c8d3d8b3f32fb0cc6b827a852bf974/c26ae/cors-without-preflight.png 158w,
/static/52c8d3d8b3f32fb0cc6b827a852bf974/ffa0f/cors-without-preflight.png 311w&quot; sizes=&quot;(max-width: 311px) 100vw, 311px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
&lt;p&gt;The browser checks out the request, sees that it is unlikely to have any negative consequences, and passes it along to the requested endpoint. In the Network tab, simple CORS requests will appear by themselves:&lt;/p&gt;
&lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 546px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/68feda98883b9759cb753687a08d3257/76aed/one-request.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 46.202531645569614%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAIAAAC9o5sfAAAACXBIWXMAAAsTAAALEwEAmpwYAAABrklEQVQozy2PTZKbMBhEuf9BcoBss0iyCJ5UyNhjZ7DNvwQYARISCCGQgG/Kqel61dX1du2UTZNinCaJlANGKI7CJI455wihIAjquiZVFYYhxnlLu8u/2+X9jouqaZooDJ3+5ndxhMpymqZHWdRUtt00jpJSyhirKsI5F0Jwzh81i1GT5jSvnq6qKkedvDEKirpWo8rSuBWWy22UQ9M0UkpCiJRSaz3PM++Y4J0ah45R0QtGqUOlYnI0xs6LWbfNmGVZ5tlYu26LscauTUujJLuHcYowwnkYp3GSeJ5HSO1oKcwowExg9L48G6zerd7/j21R8yjU0KmhY6xt2+cXQkhRFKLvndeQfL+yu4BPONwY3OiToIO/WH17e/z062u7d8oWhIhBSjVVdbvvu/PlqC8X9Oolxz/B0YuOx+wUd+dSv+Xq/NCniJ0O/jnmx3L5eurH8DoyJkklSaW0dl6w+R307lUc/M71uXvvX7L5JV8PeHXx+itdfviDmxkXb+eHWXtuZ20nZadp3TYHAOwGAYdSQdIDknClEDBAAkIG+QDvFLIeiuHpBwsAsMNnPgB1Hu3zncmQzgAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;one request&quot; title=&quot;one request&quot; src=&quot;/static/68feda98883b9759cb753687a08d3257/76aed/one-request.png&quot; srcset=&quot;/static/68feda98883b9759cb753687a08d3257/c26ae/one-request.png 158w,
/static/68feda98883b9759cb753687a08d3257/6bdcf/one-request.png 315w,
/static/68feda98883b9759cb753687a08d3257/76aed/one-request.png 546w&quot; sizes=&quot;(max-width: 546px) 100vw, 546px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
&lt;h3&gt;What does a pre-flight CORS request look like?&lt;/h3&gt;
&lt;p&gt;For non-simple requests, the method could be any of the HTTP verbs along with any other combination of headers. For example:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; body &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;possibly unstable or malicious content&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; url &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;http://api.example.com&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; request &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;XMLHttpRequest&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;POST&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; url&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;setRequestHeader&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Content-Type&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;application/json&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;send&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In this request I am trying to POST a JSON object to an API endpoint, which could potentially have destructive consequences for data on the other side of the endpoint. When the browser inspects the headers of this request it gets suspicious, and fires off a preliminary request to the endpoint with the meta data from the request:&lt;/p&gt;
&lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 451px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/f9c3294e4b2e866586ec2ae8a512287b/38070/cors-with-preflight.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 105.69620253164558%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAVCAIAAADJt1n/AAAACXBIWXMAAAsTAAALEwEAmpwYAAAC6UlEQVQ4y4WUa5OaOhiA/f9/Z3e6badd5xzvIKioC8QNJIGEuwqIINeOcNbVns70+ZDhA8+8l7xves0jeZ7Lsjwej7fb7WazEQRhvV6vViuMcfM/ek3T1B80TVMUBYRws9lgjBFCkiQtl8vtdqsoSifc/9xLkoRSyhiDEJZl2fwNx3EYY5qmXS6XqzybzX62ZFlWlmVxR9ZSVdUtGgCg3+8Ph8Msy65pl2Xp+z5jzPM8o4Ux5jgOpfTccjweb5GrqkrT9LPmNhl7NBrO5/x0OpXlN1EUeJ4bj0cYozRN7+W6rrMsu5Pr2vMOACAAEEKMMg8hCjVD0ykAuqZpQRB0Whf5Qa7rJoml6Ph6Po3Op+ElnaTJ+Hwap8kgv2yapr5v8h/SJkRaCC/LxfeF+G0hfhPmL8L8y5x/UpQRAIphkKqqPtKuiiJ/kBEyxMVakmRRXAuCNJnwy6XKz2VRVBRF43lJ1ynGlu3sz+fScfwul15XRnjlEIbHKArjKArDyHdXjP5ktO9Y/zKzT41XZvZde+Da/1Bz9imXZZnneZZllmV5nmfbtuv6GHHvuxekv+rwB1BfgPoV66879StQv+yD7adc1/V+v0cIQQhns9lkMuE4bjoVRqO5IGw4brVaKauVMpst+Lk0GHAYmw/ybrdzXTcIAk3TdF1HCCFdh/D9esAdhO8EI2oalsVMkxwOwafcNI3v+xhjQkh3Wpal6zoh5Hrv7dhTSm9Dkuf5w1a5rssYs22bUkoIObQcW6Jr/8IkSaqWoihOp9Nv4+nouk4pNQyDEJIkSZqm0QdhGMZxHEVRHMee52ma9nBVhmFkWXa5XLo1StM0jmMAgKqqEEJVVRFCWossy7dp7Z3PZ9M0AQBvb29pmuYt3T52w3wrtftwXdcwDIzxf/vMcdxwOBwMBr89BkVRBEFwOBxc1/V9PwgC3/cnk8nT09Pz83OSJL26ri8ttx7ev2edZtt2t+2WZRFCKKW2bVdV9QukJIhQO2LykgAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;cors with preflight&quot; title=&quot;cors with preflight&quot; src=&quot;/static/f9c3294e4b2e866586ec2ae8a512287b/38070/cors-with-preflight.png&quot; srcset=&quot;/static/f9c3294e4b2e866586ec2ae8a512287b/c26ae/cors-with-preflight.png 158w,
/static/f9c3294e4b2e866586ec2ae8a512287b/6bdcf/cors-with-preflight.png 315w,
/static/f9c3294e4b2e866586ec2ae8a512287b/38070/cors-with-preflight.png 451w&quot; sizes=&quot;(max-width: 451px) 100vw, 451px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
&lt;p&gt;The server at the endpoint responds to the pre-flight request with a list of authorized headers, including acceptable request origins, content, and actions.&lt;/p&gt;
&lt;p&gt;Ignoring for a moment that the requests fail (because api.example.com does not exist), the non-simple CORS request produces two requests instead of one:
&lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/9715111fcaee8540f550ff1d7f320160/61c63/two-requests.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 33.54430379746836%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAHCAIAAACHqfpvAAAACXBIWXMAAAsTAAALEwEAmpwYAAABOUlEQVQY013IyW7bMBRAUf3/b3WRVYsCjlPLkm1xeJypgU4kDqJe4WbXu7o4DSPEOgcAjIP3nnOulBJCaK0ZiPvAx3FilBrrpJRKq5cz7pxTSjau6314clB2KdM0GeuMdSGEZVmEsqCssd4ao7W21s7/+v4YY7N9LkeJNW9H2Wpej7zt8Qs4ewzk8RgIpZfLH0IopVxIyUGAkJQyQqiUqvn5mO9j7V3pXbn7+nuY3q5W+KCNjinlnEFI63zZ91JyzrmUsq6bMTbn3EA70NONnm6MWP6spAPash+X5Xk+xxBiSisd1r5bb/1mbUzpJSF8KRVTavqrvp5F+w5dq3t/dDS0J/52nhOHPcZcMSmTOewANYQD8TiOWuv3NB8e2xF/abyO+GGwn/DkXjInnCPKJ4pPHDdExAP/7y8M3IRNXoKdcAAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;two requests&quot; title=&quot;two requests&quot; src=&quot;/static/9715111fcaee8540f550ff1d7f320160/f058b/two-requests.png&quot; srcset=&quot;/static/9715111fcaee8540f550ff1d7f320160/c26ae/two-requests.png 158w,
/static/9715111fcaee8540f550ff1d7f320160/6bdcf/two-requests.png 315w,
/static/9715111fcaee8540f550ff1d7f320160/f058b/two-requests.png 630w,
/static/9715111fcaee8540f550ff1d7f320160/61c63/two-requests.png 693w&quot; sizes=&quot;(max-width: 630px) 100vw, 630px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The result of the pre-flight OPTIONS request will determine if the second is ever sent on to the endpoint. This is how browsers keep your application data secure from malicious or unintended changes.&lt;/p&gt;
&lt;h3&gt;Why OPTIONS, and not POST?&lt;/h3&gt;
&lt;p&gt;I found &lt;a href=&quot;http://stackoverflow.com/a/16945321&quot;&gt;this great answer&lt;/a&gt; on stackoverflow that explains why the creators of CORS made a new request type, &lt;code class=&quot;language-text&quot;&gt;OPTIONS&lt;/code&gt;. Before the CORS standards were introduced, neither browsers nor servers knew how to handle cross-domain requests. Browsers would throw an error, but servers would process the request without concern. Inventing a new method type that CORS-enabled browsers AND CORS-aware servers could handshake with ensures that both sides are sensible to the meaning of the pre-flight request.&lt;/p&gt;
&lt;h4&gt;RESOURCES&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Learn more about the web standards at &lt;a href=&quot;https://www.w3.org/TR/cors/&quot;&gt;W3C&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Find out more about how CORS is &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#Simple_requests:&quot;&gt;implemented at Mozilla&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Find out what web browsers support CORS at &lt;a href=&quot;http://caniuse.com/#search=CORS&quot;&gt;caniuse.com&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[keighty's 2015 - by the numbers]]></title><description><![CDATA[2015 has been a very eventful year. Not only did I write and launch an ebook about my code school experience, but I have also built and…]]></description><link>http://katieleonard.ca/blog/2015/2015-12-26-keightys-2015-by-the-numbers/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2015/2015-12-26-keightys-2015-by-the-numbers/</guid><pubDate>Sat, 26 Dec 2015 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;2015 has been a very eventful year. Not only did I write and launch an ebook about my code school experience, but I have also built and launched a book site, competed in a national &lt;a href=&quot;acbl.com&quot;&gt;Bridge&lt;/a&gt; tournament in New Orleans, celebrated 10 years of wedded bliss, spent 3 weeks traveling in the Mediterranean, and joined a new team at work where I get to deep-dive into JavaScript and browsers. Checkout my infographic for more!&lt;!--more--&gt;&lt;/p&gt;
&lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/7a454cc2d1409936030a06e1f995ebb2/5a190/2015-year-in-review-infographic.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 250%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAyCAYAAABcfPsmAAAACXBIWXMAAA7EAAAOxAGVKw4bAAALtElEQVRIx3WXeVRVV5bGDyKiolFAHCpRHKJxikZleIAt4mMeJTE4gCPIIDM4UmhwYHhMj+lN99734KE4xKhlqwmaxISkUllJa9KpXkl6ra7V3UnFASWCVtRUVVK/XveCsXpV9x/f2vucffZ3v73Pufe8J24WBnIjN4ibeTpu5g9icBz01C8IHIyrtjCQW0UBQ/YfIdRF9y2+PP7NePqOzOdO+WIenxvPgGk6vfuW8EB5jjsHFvHw+ERt3VOygP+b8PZOPy35gTyVHy88w6PT3ty3+mr24Qkf/np1JANt0/n5I1fuNT7PzQLdENn/Q3ijIJA/Zofwwwkf+ltmakpv71nKn7omaeNHZ7y4e2Q+9+pn8+duDy32hFRV+vctUCF6iwL4+bQ3fOLC960z6LdO4y/dHvx0fjy3yl7i8TlPHlt8eXB8ovawG6V+fFeg47vCwH+ARvhlXhA9pf5cLQng4cGF3C/259ahhXySr6NfffLeJfTkhPBz/Wx6dy9joCiA+6V+PCj1Y6DEX7NPoCoVb6eHskS3nvMbV/F6qh7TugjyYpJoSYmiI03PyTQ95zeH0bUugq93BHNmcxinNq1C3hDOG5vDsK6PoDNNj7IhnP8u0CHey1jB9rhE6lKi2BabRHpsEqVJcexMiiMx/GUq10TzVW4QCeEvawl58QmUJsazLjKZnLgE0qJXsy4qGWeqnr7iAMQ3BYHcKAzkP/N1/HtukIYvc4O15CdQ4/+2I1gryZ4arq39r3wdfywI5KvcYG2sxm6rJV/NWMGxNL3W1B9K/bBvCGdbTJKmSjv0hYF8U6Dj0taVGrmarCb2FfvzbUEgd4sD6B06RtqmvLUtlA1Rq9kck4TqH3klGn3YGg6/EqOVsm91HLnxCfw6OZZXI5O1VuyIT2BtZDLtqXq+L/Ef2uEAbqoKP8tZjrwhknNb9HyYGcqV9DCObYxASY3Esj6K7vQwXt+k561tK6hNieLNbaHaZpjXR2rl3in257uiAG4MQTwoWgK75vJT6QL+UrqAH4vn8dcSdTyPv5XO52875/FjyWL+VKTjp5JAHhXpuFfox93CpdzM9+deQRADBUH0D0F0W8M5UpNHU106zQ3bcZrzaDflobTmYmrMpK5+BxeMURQZfAg3eBNj8KbKNIPTyosYLc+TWOtNXK0XyXUTWF3njej7dAwb7BVMrDrPsrbfkP3Pn7Ll7MfkXbxG/sVPmG68zC7bDubZBEIWNF6excB1Px5/vpT7n/nTefUFhEMgpMG44PeCzrOxPHv4PLrGoxx482OKzvZQfLaHvec/YGHDJQ5ZMpjfJig4NxX+NQCuvQjXFsL1+fCFH5ZLsxBmgZvVBcG/CL56dxoXLgRz5ZI/H1wJ1tBzJYTrV/3Y01nAPnMOOqvg/Lt+fN3zCr/viefz91fz9ttpfP1BAl9/GMQYeRjCKhA95+ZSb47npDOQ1zsDOO4MpKsjkBNOf044/WiVI1GkKIJsgotXA/iyZw3ffrSK311N4fzlDK6+s4kvesIYpwwRck1wvDMYgzmRZimGVikasxJJsxRLky2Wjs4wHr0zimktw9l/0VcrkWsLBnF9LnyxhK7LcxAWgYva54HfumO1R2CSIqkzx2O0xNBsi6beHKfBYg+n//JYXmhzx01x5Z13F8FnOvgsQLOfvr+UqY6RGuEwmwvi80u+mhKTHIlNWYVFCceq6If8CJqkGLqPLsNPLccicJcE7d3PY7g4jfWvezNKHpwXqjrr0C6/eWoRB1vWUG+Jp8kaoz2gwRJHgyUWsyMKegRL2p5jpDSRUVYfvGQf3G3eCLMno20TGStNxEONSd6IP1zxwWBKxO4IpdkajdEaS4stSvNV0kZrDN2dfkQ7luPpiGKGCnsk0x16ZrTHMt0Rw2x7NC/YE/BVViAefezGyWPBNFjikex6bHY9smOV5luVcOR2PdfPzGSDcTx+jZ4saBmLh8WNSaaR+DWNY1arB0IahqttOC62YYO73H3yRVptUZhskVikcCxSBGYpErMtAsURTv97rpRWTeGVGm8qDk3FfGAm2VWT2Vo9keyqSYw3uT7t4X9cnUC5OQWzI5xaJZZKKZE6JZZaOY4jtiSq5ESschgb20bg1TaChS2jyKyezLNtI1hXO4HEOi9cbUOvnmofnvThW9McPjIH8E3rXG6Zn+fmEG6YZnPLPJveE1N4sWkMwjgS0eQ+mGhxwa3VTbPC5IqrOm8ehnh4eDYflCawZ28h18ui6Ct5id4Sf+7sXEbvrqXczdLRb3uOxfVeiOpxeFRMxr32GdyrPRlePwb3I964V3rjfthHG4s7DfN4rzwOqSqFDysjuFv2EnfKl3KnfAl397/EH0pC+b7jWV5oGYlodENUj0VUjkMYxuBS9QzC6IaoH4kweCAaRyC+ODOH948v43G3Cw/fGsbj7mE86nblz92COxfGcuV4EN+dnkyC0YdZrZ4sbPVifrMXM4wTmN44Ed+mCfgaffA1Dvpipnk4c22CEudcSpVkSpQYdslR7HUkkdo+hV9ZBSuaxrFu/x4Cyg4SvLec0IpqSoy7KWsuZn9zEftbCqloyaesqRihvjaBx4YTZ2kkudxIQ1k+tr2ZRFUoJCsFjG0XeLe4E5K7D98tCr5pbUzJqueQkodR3k6rfRtNSgY2xyYa5QzEOLsgy5mIX8N5sh1dbGpo5dX6NtaYOllpfIOko/PxbhH4Z5ezJPMoC7fKTM+spdycQ72USZOcToOUgUnZTJ1tO2J112SijCb0lrNknXmPtFPvsvHkO2SevoLO+AaJlv3EKB4sy9rNggw787eamJpp4DUpj3opS1PZIGdiUrZQK2Uhdh1bzeLaU6yqbyO40kxYYwdBde0E1tgIqrMQYuxkrz0QfcU+FlS0sehAPYuPtHLImkuznE6LvE1TaVM2akrF2uM+hLXY2VpxhJ0Hyyh6bS979pfy2mulxB8yE2M9xKt2D1rbUjksF1Et7aBWztHUPCnZKGdgUUuWMgd7mH80AT9DF8sa21ltP0uy8ga6BgV9vZPkrnlMbxMcM6dozTcrm7VkVZ0Ks7KFNmUrij1VIxfqbRXe5cYWi4Hl1adIbeoi1XiUkOozpNtzmdQhmNYymg7zWqqkXE1F/RAapO00K4MKrcom6qXtCKFefTZBStc0tnREsNYezKv2YDKdepZ3empf49lto+g0p1Aj59AoZWgE6hFRraquRdmGZE/TYkL9UoR2eDLHMVy7qP06XdAfc2OYLJhlH8EK53jmto1CMq2nWs7VVDXK2zFI2RpUv17O1IgNtmzECJsLu45PJdrprV3WyZ2TyO2aqn1FVnV4UnzyORa0jcZuUhXu+IXwScmqOrV3askNWskWQbjTk3GSq0Y4RRlBQPtYzR8vDeefnOP4VYsbnea1/6tktV8aofyEcONTwrCO8UQ6PVnk8CDO6cWWY5NZ4PAgxulFiPMZjbDDvJ4q+emm1ErZ1GkHO4MGefvTg61+tkdLw/BV3Jksj2CJY4xGNEF2Y4YykuGyYGbrSGTTBg5J+dTYsqmRsqm25Wi+qlQlbpG3UmXLQbhaBS5Dd65aZoBjLC87JwyOh+7bOa2jcZjWcciWT5U1RyPTrDWHWluWhmZpGw3qu6z9BPs7rOwaT8oJH4QyNKcIJplHsKulhHJ7MQZ7FoftuVQo+RpqHNlU2ndQ68his/kwIsngxepabw0JNV6sNUwgtW4iCTWeJBu8ia/1JLNyMqW/3ktzdRZOQxpy9WbM1emYqjOw12xGqdmMtSadrQeqEAM7Q+gvDGJgz3J+qFzFwMGV3NuznIeGcAZ2L2egNIT7B0K5XxbA7WIdvftXcPfISnp3B9O7M4jbe0LoLVvOLfVf7a5liHtKNHcMYdzcE8Q9OZq+1ghuH1hOf2ccfS3h2libb4ukrzaMPsNK+q2R9EtR3DNF0m+L4m5lKH2GMO5JMYhbJYGouFkcyK1SHbdKdIN+8eD8Lyh+uu5pXDeY88taHf8DHRIjr+7lEWAAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;2015 year in review infographic&quot; title=&quot;2015 year in review infographic&quot; src=&quot;/static/7a454cc2d1409936030a06e1f995ebb2/f058b/2015-year-in-review-infographic.png&quot; srcset=&quot;/static/7a454cc2d1409936030a06e1f995ebb2/c26ae/2015-year-in-review-infographic.png 158w,
/static/7a454cc2d1409936030a06e1f995ebb2/6bdcf/2015-year-in-review-infographic.png 315w,
/static/7a454cc2d1409936030a06e1f995ebb2/f058b/2015-year-in-review-infographic.png 630w,
/static/7a454cc2d1409936030a06e1f995ebb2/5a190/2015-year-in-review-infographic.png 800w&quot; sizes=&quot;(max-width: 630px) 100vw, 630px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
&lt;h4&gt;RESOURCES&lt;/h4&gt;
&lt;p&gt;Interested in making your own infographic? Try &lt;a href=&quot;http://www.canva.com/&quot;&gt;canva&lt;/a&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[faster asset loading with Cache-Control]]></title><description><![CDATA[My side project (Virtual Playbill) is an image-heavy application, and I used YSlow to find a few quick performance wins. The first ‘F’ I got…]]></description><link>http://katieleonard.ca/blog/2015/2015-11-27-faster-asset-loading-with-cache-control/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2015/2015-11-27-faster-asset-loading-with-cache-control/</guid><pubDate>Fri, 27 Nov 2015 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;My side project (Virtual Playbill) is an image-heavy application, and I used YSlow to find a few quick performance wins. The first ‘F’ I got was for No Expires Headers:&lt;/p&gt;
&lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/e9369c390ce5634ca304f8e5babfef6d/ecf19/add-expires-headers.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 26.58227848101266%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAFCAIAAADKYVtkAAAACXBIWXMAAAsTAAALEwEAmpwYAAABD0lEQVQY0zXH207CMBgA4L3/S3jjjcEILkQTI7oQDRecNuZk0LJDS0u3MtsVBlNhv9HE7+6zAj4udE0Lk8oyzUuSmzjTqTTRRmVqB9AAAJzPUEjQBTR//Wf5wYPgxTJa44hRmsUpl9n2y5i6qurv00l/gH3ZvDyc+vdNz/7cVwN+7HTvrlutm3bbot0r5E6mT4+zvuP3n+eDV51EKgz0mujdPueMe2OBFowxSaLRIr0YrDq2fdtpO45jvYc9wbbhihIqUMRWCY9TvsC0NPu6rgmlKEkIY/GbjyZDPB2xwGOBXwreAFh4M5TqiHhBpSGyTPIyzpTQFQAcDgellODcc90lWobzXzPfdz0XY2yM+QGWowfoKWiztAAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;add expires headers&quot; title=&quot;add expires headers&quot; src=&quot;/static/e9369c390ce5634ca304f8e5babfef6d/f058b/add-expires-headers.png&quot; srcset=&quot;/static/e9369c390ce5634ca304f8e5babfef6d/c26ae/add-expires-headers.png 158w,
/static/e9369c390ce5634ca304f8e5babfef6d/6bdcf/add-expires-headers.png 315w,
/static/e9369c390ce5634ca304f8e5babfef6d/f058b/add-expires-headers.png 630w,
/static/e9369c390ce5634ca304f8e5babfef6d/40601/add-expires-headers.png 945w,
/static/e9369c390ce5634ca304f8e5babfef6d/ecf19/add-expires-headers.png 948w&quot; sizes=&quot;(max-width: 630px) 100vw, 630px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
&lt;h3&gt;What is an Expires Header?&lt;/h3&gt;
&lt;p&gt;Loading the page requires slow and expensive network calls to download all the JavaScript, CSS, and image files. If someone visits the page more than once, I can avoid using the network by storing a local copy of the files in their browser cache — temporary local storage that is designed for quick retrieval. I can tell the browser to cache a copy of files that don’t change very often by setting Expires headers.&lt;/p&gt;
&lt;!--more--&gt;
&lt;p&gt;When a web server receives a request it adds some metadata to the response in the form of HTTP headers. Headers are key-value pairs that tell the browser information about the file it has received, such as how big it is (&lt;code class=&quot;language-text&quot;&gt;Content-Length&lt;/code&gt;), what kind it is (&lt;code class=&quot;language-text&quot;&gt;Content-Type&lt;/code&gt;), and how long the browser should cache the response (&lt;code class=&quot;language-text&quot;&gt;Cache-Control&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;In the case of Virtual Playbill, all the images are served from AWS Simple Storage Service (S3), and there are a couple of ways to add headers.&lt;/p&gt;
&lt;h3&gt;1. Tedious Manual Addition&lt;/h3&gt;
&lt;p&gt;You can add headers manually to a single asset stored in S3 using the metadata section:
&lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/5a570ca789141ac6cdfca361556fba3a/dba9a/add-metadata-in-s3-0.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 58.22784810126582%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAIAAADtbgqsAAAACXBIWXMAAAsTAAALEwEAmpwYAAAB+0lEQVQoz32RS2+cMBSF+cFdd99t1VXXVf9GV2kUqcpDVaPJhIcHMjCDeYMHbMAYm2tXwyRq1UWP7sILH53v3mMZY6SURVl2XccYG8fRrAKAsizDMKSU+r7/03ZfwrCqKs91MU6MMZxzq++ZYzsIIdIQPwgQQq7r2rYdRdF+v7dt23Ycb7tNv372txtvt4txLKU0xvR9bwkhqrIqiqLvh7Y9nQhp6pqQZnhV39RVO47i43vmbjrOZyEuXEopCwCMMXme7XaoKGvHRXlRN6StakJO3TjJWShuDH+8nwJ/MmaaZgB9We1s5hPHOPZc9yXEQYiPSb2P0ijOwmOeFG1F+pwMBGfF3W3WTjVhoLU2Rhtjaa2FEDuEPA/tXwL7+RnjOEuTNE2yNB2H4RKi5QxFsr5eY8/Ji1Jpmj5tNp7nRodDXTeUMUrpMDA/OV0h9pCAVy1OqZ5zaRdqm6unTD7l6leiLKVU0zSEkInzWcozkQa9bhVRcxPrH0F/7Y/fA3F3EPdHcRok44pyySZpGW0Y7TDGlwJgHa0B+MDjA/Mchpw6q4ZZs0n106L/xgYASrumacqqnmhn0uPycD3ffBO3VzLcAWv1WofReoXSC/zR+WBd1x4xbhI8f3gnvnyS9uPSEnijgGUVwGXgH/M8z+M4inE4e95qgPN/0P/VbxELnmLxxGhhAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;add metadata in s3 0&quot; title=&quot;add metadata in s3 0&quot; src=&quot;/static/5a570ca789141ac6cdfca361556fba3a/f058b/add-metadata-in-s3-0.png&quot; srcset=&quot;/static/5a570ca789141ac6cdfca361556fba3a/c26ae/add-metadata-in-s3-0.png 158w,
/static/5a570ca789141ac6cdfca361556fba3a/6bdcf/add-metadata-in-s3-0.png 315w,
/static/5a570ca789141ac6cdfca361556fba3a/f058b/add-metadata-in-s3-0.png 630w,
/static/5a570ca789141ac6cdfca361556fba3a/dba9a/add-metadata-in-s3-0.png 652w&quot; sizes=&quot;(max-width: 630px) 100vw, 630px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
&lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 614px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/7ebc7fdd594cd20dc458658877686426/e9131/add-metadata-in-s3-1.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 91.13924050632912%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAASCAIAAADUsmlHAAAACXBIWXMAAAsTAAALEwEAmpwYAAACPUlEQVQ4y42TS2/UMBSF5z8jFagQ3fMTWLFhREVZsWMByw6LoiK10tDMTCaOHeftJH7GsWPkpKVI7RS+RaQk9/j4Hl8vKO3CcLffR4QQCGEYhrvdLgiCOIbIA/fhPgIgSRII/ZckwcaYcWIhpQQgAgBIKUtPgTGGENYTeZ5DGMcxhBCmOEUI5XlujLETi3EcnXNFUUQRoJTGcVwTIqTsKGWMW2vdA2aJc86LrbVZlq1W33d79PP6JgjRegNudiDYxfu4yMoOZU1atnnVQVwnecNlfyt2zgnOt5vNxcWPKIqur66iCGCMcYIRQkVRWuud5iatHefXe3GappeXl+fn59vtJggCjHGKcZqmWZaVpRe7Ayystb4uz6q6ZowbYx52eAjvTClNUDIMg3POTNj/w4sZpTWp66qSUs75eeYmx/Efzg0hAEQJQlrrv3brH865p5yNNSlOQRQVRcE577qWMUY7KoTsmGRCPeVsje26TgihlOKM04m2bThXjPd/jvTROfHb7nXPGKuruqoqpdT8u+8VZ6xrGwRjQhqttVK91ppzb3B/zm3bEEI454xSKYTWvohSVhR5lmZN03DO9R19750447eB+WjvJsFaq6dLM1mpOcJxHM0dvkBrIYR3HmyfNqAsK1KXWYZlb5xoBj1MK1rGWJLgtm0PTNhoqCRcDuzra3rx7tuXz5+Wy4+nH87OzpbL9+v1WiklpTwYmBv9vRvQyv06ffvm+bMXr46PX56cnBwdHa1Wq7mXR51/AyzY/jJRoylNAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;add metadata in s3 1&quot; title=&quot;add metadata in s3 1&quot; src=&quot;/static/7ebc7fdd594cd20dc458658877686426/e9131/add-metadata-in-s3-1.png&quot; srcset=&quot;/static/7ebc7fdd594cd20dc458658877686426/c26ae/add-metadata-in-s3-1.png 158w,
/static/7ebc7fdd594cd20dc458658877686426/6bdcf/add-metadata-in-s3-1.png 315w,
/static/7ebc7fdd594cd20dc458658877686426/e9131/add-metadata-in-s3-1.png 614w&quot; sizes=&quot;(max-width: 614px) 100vw, 614px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
&lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 627px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/6d5ba2f3c6febfb6bd13cbb63c0f3821/e9c9b/add-metadata-in-s3-2.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 103.16455696202532%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAVCAIAAADJt1n/AAAACXBIWXMAAAsTAAALEwEAmpwYAAAC+UlEQVQ4y4VUbW7jNhTURXuIHqg32F9Fsdj+aLJFiiRtYCdxV7GtWJYsiZREyiYlUhLFz4K2mt0Wu+1gQJAQBm8471EBhHC73YAC1HUdvUab7fblJQzDcJ8kh8NhH3skSVKWcL9P0jShtHXOWWustQGh5JAd6hp1XYcxRgjVVYUQZoxRQhCqIQBlWVZlWdd1VVX90J/FHoE7I45jAGBeFFH0SkhL245QyvigjTPGKWP1TKe0MeeyXmyMEUJE0TZ8WW+iZBvncQqjfb5Lil0KQUVQwwCiDeEVbkvUYsKMsZeSgdaaUvr89BTH8XbjURRFCSGEAADAOfcmtbZaew9ae5oznQuUUnmeLxaL9WYTRa9lWWKMm6Y5ejR937tvI+CcAwAwQm3bTdP07+/GGCnN6sHcX5t4Yx7vzPLWr+tno3VgrUUIHZvjJUPzBq2NtTJLdEflzc/Tx/fy4Ubef1RP9+r+Wq0eTM/8nS8NwghLKY2dldY5BQ7yEFtnp7srcXc9LW/V4jf1y4/ywzv56weVRD5tQkhdV4x1s1Xrw7Qt0U939mxcOzfTWqWUMkafGQx9n6ZplmWn04lz3nVd11I+DPzqPQFQaOusscan7VffYzNvrA2EEG3XjePY9z1jjLctt45d/cQebjvtxCjsbOUz7N9nP2F9P5DjCWPUYOzbF6/tux+6aeItLUtYwlxNozXKaKW1opQKIS59CPzt2rY4ioZbNLpjUrDvv4P7/MgGcjyeaLsGbA15CIdlNuJ2lGKklI6jmCsrpWGF0jRNyxoufhd/3EjnxDBKKZXWg3J00HRQtFeT8s6mSarzJuimU9nk+SFbrZ5fPv0Z7ZOmH501jDGMsJ+2ulJKfn3ClFFiGiGEYfgpiqJ4t+Odf7GXCIdh4H3v58W5C/8hvkQHIQjDkBByOp2GYXDOaa2/jNd8DbO4hHC1WqVpGu92GDdCjNMk3x79tzCLi6J4enx8XC6zLEMIZVl2qf/fmP8kSqlpmsZxNMa8Paf/Ff8FKPalLLKAchcAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;add metadata in s3 2&quot; title=&quot;add metadata in s3 2&quot; src=&quot;/static/6d5ba2f3c6febfb6bd13cbb63c0f3821/e9c9b/add-metadata-in-s3-2.png&quot; srcset=&quot;/static/6d5ba2f3c6febfb6bd13cbb63c0f3821/c26ae/add-metadata-in-s3-2.png 158w,
/static/6d5ba2f3c6febfb6bd13cbb63c0f3821/6bdcf/add-metadata-in-s3-2.png 315w,
/static/6d5ba2f3c6febfb6bd13cbb63c0f3821/e9c9b/add-metadata-in-s3-2.png 627w&quot; sizes=&quot;(max-width: 627px) 100vw, 627px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;But I have more than a hundred files to change (yawn).&lt;/p&gt;
&lt;h3&gt;2. Write a Nodejs Script using &lt;code class=&quot;language-text&quot;&gt;aws-sdk&lt;/code&gt;&lt;/h3&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; aws &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;aws-sdk&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; s3 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;aws&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;S3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; params &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;Bucket&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Your_bucket_name&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;resolve&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; reject&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  s3&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;listObjects&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;params&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;err&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; data&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Something went wrong when retrieving the list of objects: &apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;resolve&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Contents&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; image&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Key &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;imageList&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;collectImageParams&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;imageList&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;imageChangeParams&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  imageChangeParams&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;forEach&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;params&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    s3&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;copyObject&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;params&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;err&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Oops! Something went wrong with copy/replace for &quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; params&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Duplicating a file in S3 will change the metadata.&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// You can make sure the new file has the same&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// access control by passing through the right permissions&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// and ContentType along with the new CacheControl header&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;collectImageParams&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;imageList&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; imageList&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;imageName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; imageParams &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token string-property property&quot;&gt;&apos;Bucket&apos;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; params&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Bucket&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token string-property property&quot;&gt;&apos;ACL&apos;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;public-read&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token string-property property&quot;&gt;&apos;MetadataDirective&apos;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;REPLACE&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token string-property property&quot;&gt;&apos;CacheControl&apos;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;max-age=2592000&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token string-property property&quot;&gt;&apos;ContentType&apos;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;image/jpeg&apos;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    imageParams&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Key &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; imageName
    imageParams&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;CopySource &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;/&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; imageParams&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Bucket &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;/&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; imageParams&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Key
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; imageParams
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Still.. I don’t want to have to run this script every time I upload a new file (yawn)…&lt;/p&gt;
&lt;h3&gt;3. Add Headers Every Time You Upload&lt;/h3&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;S3Upload.prototype.uploadToS3 = function(file, url, public_url) {
  var this_s3upload, xhr;
  this_s3upload = this;
  xhr = this.createCORSRequest(&apos;PUT&apos;, url);
  ...
  xhr.setRequestHeader(&apos;Content-Type&apos;, file.type);
  xhr.setRequestHeader(&apos;x-amz-acl&apos;, &apos;public-read&apos;);

  // Set the Cache-Control header for every file upload
  xhr.setRequestHeader(&apos;Cache-Control&apos;, &apos;max-age=2592000&apos;);
  return xhr.send(file);
};&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;Great Results&lt;/h3&gt;
&lt;p&gt;No matter how you add the Cache-Control header, the result is amazing:
&lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/a47aba5d562f1117c2558031135f7418/f96df/cache-control.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 68.9873417721519%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAOCAYAAAAvxDzwAAAACXBIWXMAAAsTAAALEwEAmpwYAAADsklEQVQ4yy2Q24sbZQDFx7/B/0K8gBQrCMV3BX3qgvogCIKPIvTFhz7oWvShBdGCVhCxFVq33dq9pntJ3KSbZLPdJJNkk8wkmcncM5edSeaSuXz5juzWh/P248c5h3n8zwZz5k0ZAIwjdpmfN06YD+6ZL/96Mjt57+pnf1x67ZVb77x96fd3L7/+/qsffnXBned28Rfma+bjl65cvvLlm2+8dV1Y/34H7J2PGEXVVqNovgpg1XHdVVXRHhpTN7dcZJO9RtnKl4+V9X/r5m5DOm4q0QpNw8fnrDGbPOqZ/bWnh9uzldzaopv/Aa682WcUSYLtOHBdD2eei2AaohWyKBgHqNEy6paOqgzUlBRHoxmsgGAaAZWggopVxWlwiifxOj2cFknZKIPhOC4TJTlTNT2zbDsLZkHWClrEth0qJQItifyiwGWLihCQIudlOT7LSkKasfNG5lpu5qou3Ta3qRnadKLaC2YgShgJIlRNh2Xb8KcBWkELiqVilPCoSjyKfIKNboTq0MXROMKpnqAe1WFYBizDwpa9BSVQoGgqGFmWIY4laLoB5+wMwSxEO2xDtw0I6QDlMY/aaI7dfoDd7hR+FGORZRdC0zbhTBzk7By0UIeq62A6rTYEUYKiahdfvmjIQjEVCAmHZyKHIp+iwAeoDj0ssgRZkuEkPIFh6jC1CbasTciBCklVwXCdNkbCGLKivpjs+WhFHVjeDDJUHEoDlPgU+3yEY2GKIzlFGKVoJi04XgDPjrDr5eFGJlzDBqMMGxj93/BcGPhzsHYZtfoDHIt/oyL0UREI8oMIez0fmhcjTSmq5lM02Sfo1Ddxr/sT1ozneNSrghmc9iBKMvTzDx0HszCG162hXc/B6eyizfZRFGKUBj622h5GVgxQgrNmARONhSzWkC/tYafXwf6wDYbr96goyVTTdGrbNp0GIY37p9TRbApNob32gOZHCZ4NfZrvunSfj6npp5R2W3RBQP0wpi1WprpoUs+yKTPgOSKOJWIYE+I4DvHDiMR8hxiKkkETsn5nQErjjJSFiLRFmzSVmMhuSha9BsnSmEynLqk3OCKIGtEMjTCn3T76wzEESYOqW5h4IaZsA3KrjbjTRLc1QFUhOBhEkA0HJEsQpymC5nP4/hwTy0G1xoEbaBgrOpiDQmmp2hwuHbHDJV60lgSXXDX39j8Z3bzxBfnt5qf56ujGfXaeW2kG6w+aUU73kusR8Pns4V/XvPt3l+27d74p3P7zu1s7zvKPefvb/wBa+sVNkxCGLAAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;cache control&quot; title=&quot;cache control&quot; src=&quot;/static/a47aba5d562f1117c2558031135f7418/f058b/cache-control.png&quot; srcset=&quot;/static/a47aba5d562f1117c2558031135f7418/c26ae/cache-control.png 158w,
/static/a47aba5d562f1117c2558031135f7418/6bdcf/cache-control.png 315w,
/static/a47aba5d562f1117c2558031135f7418/f058b/cache-control.png 630w,
/static/a47aba5d562f1117c2558031135f7418/f96df/cache-control.png 849w&quot; sizes=&quot;(max-width: 630px) 100vw, 630px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h3&gt;Resources&lt;/h3&gt;
&lt;p&gt;For more information about HTTP headers and the browser cache, check out these useful resources:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://www.mobify.com/blog/beginners-guide-to-http-cache-headers/&quot;&gt;Beginners Guide to HTTP Cache Headers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/http-caching?hl=en&quot;&gt;Optimizing Content Efficiency Using HTTP Caching&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[javascript object property meta properties]]></title><description><![CDATA[JavaScript Objects are complex types, and even defined properties have a control panel of their own. You can view the content of the control…]]></description><link>http://katieleonard.ca/blog/2015/2015-11-07-javascript-object-property-meta-properties/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2015/2015-11-07-javascript-object-property-meta-properties/</guid><pubDate>Sat, 07 Nov 2015 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;JavaScript Objects are complex types, and even defined properties have a control panel of their own. You can view the content of the control panel using &lt;code class=&quot;language-text&quot;&gt;Object.getOwnPropertyDescriptor()&lt;/code&gt;, and flip their switches using &lt;code class=&quot;language-text&quot;&gt;Object.defineProperty()&lt;/code&gt;. &lt;!--more--&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Note: These property descriptors are for &lt;code class=&quot;language-text&quot;&gt;own properties&lt;/code&gt; — that is, properties that are directly defined on an object, not those that come along for the ride on the object’s prototype chain.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;The property descriptor holds meta data&lt;/h3&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;&gt; var me = {
  name: &quot;Katie&quot;
}

&gt; Object.getOwnPropertyDescriptor( me, &quot;name&quot; )
{
  value: &quot;Katie&quot;, // the value associated with the property
  writable: true,   // true if the value of the property can be changed
  enumerable: true, // true if the property shows up during enumeration of the properties
  configurable: true // true if any of these meta properties can be changed
}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;Change the property value&lt;/h3&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;Object.defineProperty( me, &quot;name&quot;, {
  value: &quot;keighty&quot;
})

me.name // &quot;keighty&quot;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;Make the property read only&lt;/h3&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;Object.defineProperty(me, &quot;name&quot;, {
  writable: false
})

me.name = &quot;k80&quot;
me.name  //&quot;keighty&quot; -- actual value of me.name did not change&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;Make the property hidden from for-loops (or any enumeration)&lt;/h3&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;me.hobbies = [&quot;bridge&quot;, &quot;curling&quot;, &quot;tap dancing&quot;]
me // Object {hobbies: Array[3], name: &quot;keighty&quot;}

for(fact in me) {
 console.log(fact)
}
// All the properties defined on me are written to the console:
// name
// hobbies

Object.defineProperty(me, &quot;name&quot;, {
 enumerable: false
})

for(fact in me) {
 console.log(fact)
}
// Actually.. only enumerable properties are written to the console:
// hobbies&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;Freeze the property&lt;/h3&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;Object.defineProperty(me, &quot;name&quot;, {
 configurable: false
})

Object.getOwnPropertyDescriptor(me, &quot;name&quot;)
// { value: &quot;keighty&quot;,
//   writable: false,
//   enumerable: false,
//   configurable: false }

Object.defineProperty(me, &quot;name&quot;, {
 writable: true
})

Uncaught TypeError: Cannot redefine property: name(…)&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;From &lt;a href=&quot;http://www.ecma-international.org/ecma-262/5.1/#sec-8.10&quot;&gt;the docs&lt;/a&gt;: “The Property Descriptor type is used to explain the manipulation and reification of named property attributes. Use Object.defineProperty for fine-grained control over the visibility and mutability of your object’s properties.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[estimate != commitment != target]]></title><description><![CDATA[Software estimation is hard, but I didn’t really understand why until I started reading Software Estimation: Demystifying the Black Art by…]]></description><link>http://katieleonard.ca/blog/2015/2015-10-31-software-estimation-is-hard/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2015/2015-10-31-software-estimation-is-hard/</guid><pubDate>Sat, 31 Oct 2015 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Software estimation is hard, but I didn’t really understand why until I started reading &lt;a href=&quot;http://www.amazon.com/Software-Estimation-Demystifying-Developer-Practices/dp/0735605351&quot;&gt;Software Estimation: Demystifying the Black Art&lt;/a&gt; by Steve McConnell. It was published in 2006, and is very much still relevant — there are more ways to do estimation wrong than to do it right.&lt;/p&gt;
&lt;p&gt;The biggest “aha” moment for me was learning the difference between estimates, targets, and commitments. &lt;!--more--&gt;I always thought that estimates were commitments and treated them like targets. If a task took longer than my estimate, I would worry that I had blown the project plan. The source of my stress was really semantics, and a deep misunderstanding of project plans in general.&lt;/p&gt;
&lt;h4&gt;1. An estimate is a range where there is a 90% chance of finding the completion date&lt;/h4&gt;
&lt;p&gt;An estimate is not a single point in time — that is a target. There is uncertainty in software development, and uncertainty about the uncertainty.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;There is a limit to how well a project can go but no limit to how many problems can occur.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Estimates are probability distrubutions of possible outcomes:&lt;/p&gt;
&lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/2dc03f16e4a0eb7dfb4f85161eefced8/c67d4/estimation-chart.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 41.77215189873418%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAIAAAB2/0i6AAAACXBIWXMAAAsTAAALEwEAmpwYAAABCElEQVQY03WPTW7CQAyFc2EOUHXDTbhC11VPUAmpRSLQNpVSQkuYUIZMfmbssccVhFAJhSfLC8vfe3YkIt57rTURyUnMnCTJ8n05X8TFbiciIQQZUiQiRL6qKgfQD0PA4EpLLQUQGQZ7uPNGxGNsYBGZ7qd3j/fjp/HoYTSZTW6FR3utlVLWWu/9ZSkz6Sx5TjHNOIsxxoDDyU3TlGUJAHiCjzyzX2iY7/Ht0F117kH+6+pswLM9GbBx4UXqxdZ96dsvSxR6OeeIiIWdqtzGWLAAUH8U5uXbvP6YOLerg8sNqAp1e9xkji42zEydvOfATdNk2XpTbJVSeZ6vP1ftb02Vw7L1tevgPz7rzSzY4bmIAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;estimation chart&quot; title=&quot;estimation chart&quot; src=&quot;/static/2dc03f16e4a0eb7dfb4f85161eefced8/f058b/estimation-chart.png&quot; srcset=&quot;/static/2dc03f16e4a0eb7dfb4f85161eefced8/c26ae/estimation-chart.png 158w,
/static/2dc03f16e4a0eb7dfb4f85161eefced8/6bdcf/estimation-chart.png 315w,
/static/2dc03f16e4a0eb7dfb4f85161eefced8/f058b/estimation-chart.png 630w,
/static/2dc03f16e4a0eb7dfb4f85161eefced8/c67d4/estimation-chart.png 723w&quot; sizes=&quot;(max-width: 630px) 100vw, 630px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
&lt;p&gt;Most of my experience in estimating projects has been to break a feature down into small tasks and estimate those. Tightly defined requirements for a task make it easier to estimate, but there are always complications that can throw things off track. Thinking about an estimate as a range of possibilities between the best and worst case scenarios reduces stress about being right the first time.&lt;/p&gt;
&lt;h4&gt;2. A commitment is a promise to deliver defined functionality at a certain level of quality at a certain date.&lt;/h4&gt;
&lt;p&gt;You can use estimates to plan commitments, but not the other way around. If ten features take a year to develop, but your customer needs to have something in six months, you can commit to delivering four or five features by that target, but there is no way you can deliver ten.&lt;/p&gt;
&lt;h4&gt;3. A target is a single point in time, and is usually determined by business needs.&lt;/h4&gt;
&lt;p&gt;A target has more in common with a commitment than an estimate — it can have no bearing on the time estimated to complete a project, but will often define the envelope of time. Like in the previous example, the target for delivery to the customer was six months, but the commitment could be four or five features, depending on the estimates for each feature.&lt;/p&gt;
&lt;p&gt;Estimation must come before planning, and before you really understand all of the requirements for the project. More often than not, events that happen during the project will have a big impact on the assumptions made to estimate the project at the beginning. Estimates are hard, but McConnell has some awesome advice on how to get it right.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[The Clean Coder]]></title><description><![CDATA[In The Clean Coder: A Code of Conduct for Professional Programmers, Bob Martin (Uncle Bob) tells you what it means to be a professional…]]></description><link>http://katieleonard.ca/blog/2015/2015-09-26-the-clean-coder/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2015/2015-09-26-the-clean-coder/</guid><pubDate>Sat, 26 Sep 2015 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;In &lt;a href=&quot;http://www.amazon.com/Clean-Coder-Conduct-Professional-Programmers/dp/0137081073/ref=sr_1_1?ie=UTF8&amp;#x26;qid=1443288322&amp;#x26;sr=8-1&amp;#x26;keywords=the+clean+coder&quot;&gt;The Clean Coder: A Code of Conduct for Professional Programmers&lt;/a&gt;, Bob Martin (Uncle Bob) tells you what it means to be a professional programmer. Much of what distinguishes a professional from a non-professional can be reduced to responsibility: a professional is responsible for their project, their team, and their own career. &lt;!--more--&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.amazon.com/Clean-Coder-Conduct-Professional-Programmers/dp/0137081073/ref=sr_1_1?ie=UTF8&amp;qid=1443288322&amp;sr=8-1&amp;keywords=the+clean+coder&quot;&gt;&lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 193px; &quot;&gt;
      &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 129.74683544303798%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAaABQDASIAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAAMFBAL/xAAWAQEBAQAAAAAAAAAAAAAAAAABAgD/2gAMAwEAAhADEAAAAZD89atJOQG6Zz2kDDT/AP/EAB0QAAICAgMBAAAAAAAAAAAAAAECAAMREiEiMTL/2gAIAQEAAQUC0ibKXOGQFiadUs+kIw1/Q8mCN7//xAAXEQEBAQEAAAAAAAAAAAAAAAAAERIx/9oACAEDAQE/Ac3qNRX/xAAXEQEBAQEAAAAAAAAAAAAAAAAAEQEC/9oACAECAQE/AearEf/EACAQAAAEBgMAAAAAAAAAAAAAAAABEBECEiAhMkGBkaH/2gAIAQEABj8C12MYT5F/EdGMS0//xAAcEAADAQACAwAAAAAAAAAAAAAAAREhMUFRYXH/2gAIAQEAAT8hTNJ3ZbVj4ZYxIr7UmbEIBFmKGBK/hVIyvyxnmjPsz//aAAwDAQACAAMAAAAQfDaw/8QAGBEBAQEBAQAAAAAAAAAAAAAAAQAhETH/2gAIAQMBAT8QQIgyeHlrb//EABcRAQEBAQAAAAAAAAAAAAAAAAEAMRH/2gAIAQIBAT8QGhldm5N//8QAHxABAAICAQUBAAAAAAAAAAAAAQARITFhQVFxgZHx/9oACAEBAAE/ECUxfLRHk2Sp2GA6L62M9NCX0htO2rhstlYWpo9QKqUrdZuM0EVjTBGjY4n7kMoQ+YvJMd5//9k=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;cleancoder&quot; title=&quot;cleancoder&quot; src=&quot;/static/a8abf2ad0f3958cf2cc82a6cd76bedab/fe066/cleancoder.jpg&quot; srcset=&quot;/static/a8abf2ad0f3958cf2cc82a6cd76bedab/ff44c/cleancoder.jpg 158w,
/static/a8abf2ad0f3958cf2cc82a6cd76bedab/fe066/cleancoder.jpg 193w&quot; sizes=&quot;(max-width: 193px) 100vw, 193px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot;&gt;
    &lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Protect your projects&lt;/h2&gt;
&lt;p&gt;Your first responsibility, according to Uncle Bob, is to your employer, which means doing the job that you have been hired to do.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Make reasonable estimates.&lt;/strong&gt; Your project does not exist in isolation from other parts of the company. An estimate is a probability distribution of likely outcomes, not a single point in time. Many stakeholders rely on your estimates for coordinating marketing, sales, and other downstream tasks.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Meet your commitments.&lt;/strong&gt; Estimates are different from commitments. If you have committed to delivering a feature or a product by a target date, meet that date.&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;If it can’t be done, you can still commit to actions that will bring you closer to the target. Finding out if it can be done can be one of the actions to commit to!&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Protect your time.&lt;/strong&gt; An easy way to ensure the success of your project is to devote the time and energy you have already promised in your estimates. Meetings can be disruptive to your workflow, and you should decline any meeting that does not move your project forward. If you can’t decline, ask for an agenda and clear goals before you accept.&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;Sometimes the meeting will be about something that interests you, but is not immediately necessary. You will have to choose whether you can afford the time. Be careful — there may be more than enough of these meetings to consume your days.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;Protect your team&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;A team-player communicates frequently, keeps an eye out for his or her teammates, and executes his or her own responsibilities as well as possible.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Stand by your original estimates&lt;/strong&gt;, and don’t confuse them with commitments. Your estimates should protect your team from long hours, undue management pressure, and unpleasant surprises. Don’t promise what your team can’t deliver.&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;Business likes to view estimates as commitments. Developers like to view estimates as guesses. The difference is profound.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Mentor less experienced engineers.&lt;/strong&gt; Contributing to the growth of everyone will make your team stronger. Don’t wear your headphones to cut yourself off from interruptions. Making yourself available as a resource will get someone else on the team unstuck, which moves your project forward (Uncle Bob recommends using TDD instead of the Zone to pick up the stack if you have to drop it). “It is unprofessional to be a loner or a recluse on a team.”&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Protect your career&lt;/h2&gt;
&lt;p&gt;Your employer is not responsible for keeping your skills up to date. They are not required to ensure that you are aware of cutting edge technologies and languages.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Your career is your responsibility. It is not your employer’s responsibility to make sure you are marketable. It is not your employer’s responsibility to train you, or to send you to conferences, or to buy you books. These things are your responsibility. Woe to the software developer who entrusts his career to his employer.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Practice coding.&lt;/strong&gt; Uncle Bob is a big proponent of practicing code. Performing code kata before starting work will put you in the right frame of mind.&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;Professionals practice. True professionals work hard to keep their skills sharp and ready. It is not enough to simply do your daily job and call that practice. Doing your job is daily performance, not practice. Practice is when you specifically exercise your skills outside of the performance of your job for the sole purpose of refining and enhancing those skills.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Learn about the industry.&lt;/strong&gt; Falling behind in new technologies will make you obsolete. You will not stay marketable to new employers (or even your current employer), if you do not stay current.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Reading The Clean Coder was like sitting down with a mentor and asking how I can grow my career. I would recommend it for anyone entering the profession today!&lt;/p&gt;</content:encoded></item><item><title><![CDATA[keep your code close and your notes closer with a global gitignore]]></title><description><![CDATA[I like to keep my notes as close to the code as possible. When I start on a new code base, I create a folder at the top called . Super…]]></description><link>http://katieleonard.ca/blog/2015/2015-09-18-keeping-your-notes-close-to-the-code/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2015/2015-09-18-keeping-your-notes-close-to-the-code/</guid><pubDate>Fri, 18 Sep 2015 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I like to keep my notes as close to the code as possible. When I start on a new code base, I create a folder at the top called &lt;code class=&quot;language-text&quot;&gt;aa_notes&lt;/code&gt;. Super obvious, and it makes an awesome scratch pad for things I don’t want to lose. So, how can you do this without checking your folder in to source control? Adding it to a local .gitignore is one strategy, but that change will also need to be checked in to git.&lt;/p&gt;
&lt;!--more--&gt;
&lt;p&gt;The answer is to use a global gitgnore.&lt;/p&gt;
&lt;p&gt;You can configure a global gitignore file in your home directory that will ignore items in every repo on your machine.&lt;/p&gt;
&lt;h3&gt;1. Add a folder to your source control&lt;/h3&gt;
&lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/3c0bbc6be6f9a8d000bea652f4cbe934/c54b3/add_note_folder.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 53.79746835443038%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAIAAADwazoUAAAACXBIWXMAAAsTAAALEwEAmpwYAAABGUlEQVQoz5WR606DMBSA9/5P4kOYGKNTs4uXMBgwkG6ygoMIvXBpewqTiT+ITsNJ0/Sk/U5PvjNBZf2c58uPzGbU3gl35ueze+S9oS06vB/C/V5K2Z6JCanqiPO0qqmQOQOaUpEkZVkXBZdCat2052NirYy76TTGuG3bpvnr6S/wdmkEpsMuF3Bx3X7BTdOVOe0/1hBGvo8xTnFczx01d3XGRvxsmmYUxX2mAAjXr5EyAnjcwArBkwcPa2UidfWiFq6uxAD2Pc+2nTRJCsqE6O50JYByIBx4BayAnHWHjHV1pRrA4W632XiGYYThnhCiAUa07ayt25upZVplWXayvoX1ev4RFgSu61JCes+jRoUxjk/Cxg75Ez4CKTp72TRrvTwAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;add note folder&quot; title=&quot;add note folder&quot; src=&quot;/static/3c0bbc6be6f9a8d000bea652f4cbe934/f058b/add_note_folder.png&quot; srcset=&quot;/static/3c0bbc6be6f9a8d000bea652f4cbe934/c26ae/add_note_folder.png 158w,
/static/3c0bbc6be6f9a8d000bea652f4cbe934/6bdcf/add_note_folder.png 315w,
/static/3c0bbc6be6f9a8d000bea652f4cbe934/f058b/add_note_folder.png 630w,
/static/3c0bbc6be6f9a8d000bea652f4cbe934/c54b3/add_note_folder.png 727w&quot; sizes=&quot;(max-width: 630px) 100vw, 630px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
&lt;h3&gt;2. Create a file and git will suggest to track it&lt;/h3&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;➜  virtualplaybill2 git:(master) touch aa_notes/this_is_a_note_file.md
➜  virtualplaybill2 git:(master) ✗ git status
On branch master
Your branch is up-to-date with &apos;origin/master&apos;.
Untracked files:
  (use &quot;git add file...&quot; to include in what will be committed)

        aa_notes/

nothing added to commit but untracked files present (use &quot;git add&quot; to track)&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;3. Set up your global gitignore&lt;/h3&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;➜  virtualplaybill2 git:(master) ✗ git config --global core.excludesfile ~/.gitignore_global
➜  virtualplaybill2 git:(master) ✗ echo &quot;aa_notes&quot; &gt; ~/.gitignore_global&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;4. Git will ignore all folders on your machine named aa_notes&lt;/h3&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;➜  virtualplaybill2 git:(master) ✗ git status
On branch master
Your branch is up-to-date with &apos;origin/master&apos;.
nothing to commit, working directory clean&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This comes in super handy when you want to make clarifying notes to yourself without sharing them with all of your collaborators. Of course, if they are good things to share, you should probably add them to the project wiki.&lt;/p&gt;
&lt;p&gt;I keep things like daily &lt;a href=&quot;https://www.safaribooksonline.com/blog/2014/06/26/information-flow/&quot;&gt;infobits&lt;/a&gt;, backdoor patches, bits of scripts, and other things. Sometimes writing a note about something helps me remember it a little better, so I still keep my own notes, even if the info is already on the wiki.&lt;/p&gt;
&lt;p&gt;Checkout &lt;a href=&quot;https://help.github.com/articles/ignoring-files/&quot;&gt;this post on GitHub&lt;/a&gt; for this and more ideas for fine tuning what git ignores.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[hunting monkey patches]]></title><description><![CDATA[Ruby monkeypatching is a dangerous, but necessary tool. It is convenient to add new behaviours to  existing classes, or to replace existing…]]></description><link>http://katieleonard.ca/blog/2015/2015-08-08-hunting-monkey-patches/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2015/2015-08-08-hunting-monkey-patches/</guid><pubDate>Sat, 08 Aug 2015 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Ruby monkeypatching is a dangerous, but necessary tool. It is convenient to add new behaviours to  existing classes, or to replace existing methods with more customized or secure code. Once the patch is in place, however, it is easy to forget that it is there.&lt;/p&gt;
&lt;p&gt;Recently, I was trying to discern the origin of such a patch, and discovered a new (to me) function in pry, my favourite Ruby debugger: &lt;code class=&quot;language-text&quot;&gt;show-source&lt;/code&gt;.&lt;/p&gt;
&lt;!--more--&gt;
&lt;ol&gt;
&lt;li&gt;Put a &lt;code class=&quot;language-text&quot;&gt;binding pry&lt;/code&gt; below the monkeypatch so that it can be caught at boot time&lt;/li&gt;
&lt;li&gt;Use &lt;code class=&quot;language-text&quot;&gt;cd&lt;/code&gt; to change directories into the reopened class&lt;/li&gt;
&lt;li&gt;Use &lt;code class=&quot;language-text&quot;&gt;show-source&lt;/code&gt; to find the exact location where the method was originally defined&lt;/li&gt;
&lt;li&gt;Use &lt;code class=&quot;language-text&quot;&gt;show-source -a&lt;/code&gt; to show the source and location of EVERY MONKEYPATCH&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;In action:&lt;/p&gt;
&lt;h4&gt;1. Debug your code at boot time&lt;/h4&gt;
&lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/4f9f5d4e65a01855661488ce500fe8a0/00d43/step1-pry.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 39.87341772151899%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAIAAAB2/0i6AAAACXBIWXMAAAsTAAALEwEAmpwYAAABSklEQVQY02WQQW+cMBCF+f//KGpvibSp1EMOXSVqYlgMeA2OYcAeG3tsqNhVVSl9Gn1zmdG8ecUHY78ZO5/PJWOdEG3XStlzXjeczzdN46iUAoD9PxWj6Iy8dpwLIQEAEb33B537N7UdOvq9tr/Ley9iL+FTOY9EcV3XEMKd3jvvvcODFAPF+PVymM244LiAuM79oNUwqEFZYxARrUVEZy0s+NK4N+nPfX5T+XVIKx3XC++T86TnsSnlUNaqZCCuNEE2CwEka7MxZjKPl/yjSac6fnuPpaZ0s14ArHpyrbw0dfWL6xPTr9IxhbV2Yia50ISEIT1W8fkST3V8quLPlqqRQtqKCXIP44x6BoMhpG3Nyefstm29J7Tvu4vbwzt9/6CnS3rmdOIp5dvPSmk1fhpjrLV2mXnNnfdfgolpqzR1kFpIgzkY0mH7D59FxNy40T2HAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;step1 pry&quot; title=&quot;step1 pry&quot; src=&quot;/static/4f9f5d4e65a01855661488ce500fe8a0/f058b/step1-pry.png&quot; srcset=&quot;/static/4f9f5d4e65a01855661488ce500fe8a0/c26ae/step1-pry.png 158w,
/static/4f9f5d4e65a01855661488ce500fe8a0/6bdcf/step1-pry.png 315w,
/static/4f9f5d4e65a01855661488ce500fe8a0/f058b/step1-pry.png 630w,
/static/4f9f5d4e65a01855661488ce500fe8a0/40601/step1-pry.png 945w,
/static/4f9f5d4e65a01855661488ce500fe8a0/00d43/step1-pry.png 1000w&quot; sizes=&quot;(max-width: 630px) 100vw, 630px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
&lt;h4&gt;2. Reopen the class&lt;/h4&gt;
&lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/456d7c8fc156752899f2008ad47e7acd/00d43/step2-cd.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 18.9873417721519%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAECAIAAAABPYjBAAAACXBIWXMAAAsTAAALEwEAmpwYAAAA0UlEQVQI13XOyU7DMBSF4bz/E/AQ3SKhSgyVKnBIxCBoiBvbCYQ2ppCSOIOvHXwNRWw5i29zNn+Qc5GmKWOZ4JwzVlW7+8fdirWzdfyQN2r0pcKXBl9bFHvM9l58HrTOe++D4/iULAm5DklIoiheJUlRiLp+P+KzUN5sZDN/UousO6fdxbo7o2qetJf0o9pupZTBbU0dTMM4jFoP49D3vQawxoI9UHfmhJoFN8vcRCXcbYA8w1trJgMaIPD/DH9tNF4VNiptpRyi/3I4ub/rJ/sbytva7J7RsyIAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;step2 cd&quot; title=&quot;step2 cd&quot; src=&quot;/static/456d7c8fc156752899f2008ad47e7acd/f058b/step2-cd.png&quot; srcset=&quot;/static/456d7c8fc156752899f2008ad47e7acd/c26ae/step2-cd.png 158w,
/static/456d7c8fc156752899f2008ad47e7acd/6bdcf/step2-cd.png 315w,
/static/456d7c8fc156752899f2008ad47e7acd/f058b/step2-cd.png 630w,
/static/456d7c8fc156752899f2008ad47e7acd/40601/step2-cd.png 945w,
/static/456d7c8fc156752899f2008ad47e7acd/00d43/step2-cd.png 1000w&quot; sizes=&quot;(max-width: 630px) 100vw, 630px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
&lt;h4&gt;3. Use ‘show-source’&lt;/h4&gt;
&lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/c5f402c692f32a400528817a74bff8cc/00d43/step3-show-source.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 44.30379746835443%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAIAAAC9o5sfAAAACXBIWXMAAAsTAAALEwEAmpwYAAABt0lEQVQozzWR2W7aQABF/f9f0aciBVX9AZqQhFaE0AoCIbUNXhkv4202jz2erUranqf7dqVznLIoAAB5XuQZyPMcljDLsq5t1TtSSvkxlNZaSqmVtv9RSjvtcR++Hl72u9c31/fcKAwRQkWRJ3EMrgBcQRzHcZoWSf7lsvi0+3ozu/k8m83nc1jVjoKQRxlr2xTp52QaJ22N+fgwWklrtFHKaGknVYhqma5vF4u7b4sf31ejGJ3TzqVpKUWrJSwxPOV1S2ujmklUkGCACCQoxwRSXGKGsRy0xcZyY43Uznq9oX3Ae5+Q48gjRsOwPIMm4H2yias7v7o/V0sPryP0ENKHoL8/9z7kHRNaaGe7/cVIOPB4GBLehwMt5Qgw6/hQHbLhMRi3KX+K+Toal8H08ypXoXxKVMuNtdYJLhElHqMuJSfGflP6QjqPE5cy/zmub/1uFXTLM364dEuvO4B+B6ZNKoV81+6URTEMyTimA78MPBHiKkQ+jqEQ0CvL3RVuI7wH6FiwnlGre2utMeZvLefNzTpE6gbXFWsb3nScUNV2smoEIQKhAeOJYEGpZNwgrBCWQvyr/Qddae3qS5oTKgAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;step3 show source&quot; title=&quot;step3 show source&quot; src=&quot;/static/c5f402c692f32a400528817a74bff8cc/f058b/step3-show-source.png&quot; srcset=&quot;/static/c5f402c692f32a400528817a74bff8cc/c26ae/step3-show-source.png 158w,
/static/c5f402c692f32a400528817a74bff8cc/6bdcf/step3-show-source.png 315w,
/static/c5f402c692f32a400528817a74bff8cc/f058b/step3-show-source.png 630w,
/static/c5f402c692f32a400528817a74bff8cc/40601/step3-show-source.png 945w,
/static/c5f402c692f32a400528817a74bff8cc/00d43/step3-show-source.png 1000w&quot; sizes=&quot;(max-width: 630px) 100vw, 630px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
&lt;h4&gt;4. Use ‘show-source -a’&lt;/h4&gt;
&lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/cefc1300b723742d15eadd13d517d079/c1b63/step4-show-source-a1.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 14.556962025316455%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAADCAIAAAAcOLh5AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAn0lEQVQI1y3ETwuCMBiAcb//J+nSKTqUdAgq6NglkJybTdHmv23vNsPXuUD6wfNElNGUpEXBCSGUUkboqyJbHu8Pu/vtGhYMHhf/v58RcW0VtXXbfgYA69wXjHN2FGqMebI5nk+XR1ICqc1b2LyxWQWiBwCtpDKrKH9S14kJe8QBZ+m9VG6oByi1q43OmpZ1Pe8aJnQhlRqnsIQQfFj9AIH7peaAbYBnAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;step4 show source a1&quot; title=&quot;step4 show source a1&quot; src=&quot;/static/cefc1300b723742d15eadd13d517d079/f058b/step4-show-source-a1.png&quot; srcset=&quot;/static/cefc1300b723742d15eadd13d517d079/c26ae/step4-show-source-a1.png 158w,
/static/cefc1300b723742d15eadd13d517d079/6bdcf/step4-show-source-a1.png 315w,
/static/cefc1300b723742d15eadd13d517d079/f058b/step4-show-source-a1.png 630w,
/static/cefc1300b723742d15eadd13d517d079/40601/step4-show-source-a1.png 945w,
/static/cefc1300b723742d15eadd13d517d079/c1b63/step4-show-source-a1.png 1200w&quot; sizes=&quot;(max-width: 630px) 100vw, 630px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
&lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/29bc3c860250e5c5c3df3faf2942d9ce/3c492/step4-show-source-a2.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 18.9873417721519%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAECAIAAAABPYjBAAAACXBIWXMAAAsTAAALEwEAmpwYAAAArUlEQVQI11WO20rDUBBF8/+fJAhSxC/oQ+U0JqFUkxhyLnOStDN75oi1D3a9Lval6s/9OIzezylF730IIcX0C1GMkYhyzgKUUsyKlQeqoZ6WOQAZHM0u/51aabw2s75/4zCKm8RN2PfylW5dpVTOnT7rdmjbzc9YshBh3YSS8VW0vDa8++Anxy81Px/5rZPjBL/qPdx13bYGgIAFWO+jZn+axVh0E2XoVVTwcPwH0gXlI+qkIiAAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;step4 show source a2&quot; title=&quot;step4 show source a2&quot; src=&quot;/static/29bc3c860250e5c5c3df3faf2942d9ce/f058b/step4-show-source-a2.png&quot; srcset=&quot;/static/29bc3c860250e5c5c3df3faf2942d9ce/c26ae/step4-show-source-a2.png 158w,
/static/29bc3c860250e5c5c3df3faf2942d9ce/6bdcf/step4-show-source-a2.png 315w,
/static/29bc3c860250e5c5c3df3faf2942d9ce/f058b/step4-show-source-a2.png 630w,
/static/29bc3c860250e5c5c3df3faf2942d9ce/40601/step4-show-source-a2.png 945w,
/static/29bc3c860250e5c5c3df3faf2942d9ce/78612/step4-show-source-a2.png 1260w,
/static/29bc3c860250e5c5c3df3faf2942d9ce/3c492/step4-show-source-a2.png 1300w&quot; sizes=&quot;(max-width: 630px) 100vw, 630px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;</content:encoded></item><item><title><![CDATA[Don't count your chickens if they are ActiveRecord objects]]></title><description><![CDATA[You may believe that , , and  are fairly equivalent: But, beware of  in Rails!  and  are largely equivalent, but  issues an additional query…]]></description><link>http://katieleonard.ca/blog/2015/2015-05-07-dont-count-your-chickens-if-they-are-active-record-objects/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2015/2015-05-07-dont-count-your-chickens-if-they-are-active-record-objects/</guid><pubDate>Thu, 07 May 2015 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;You may believe that &lt;code class=&quot;language-text&quot;&gt;#length&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;#size&lt;/code&gt;, and &lt;code class=&quot;language-text&quot;&gt;#count&lt;/code&gt; are fairly equivalent:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;irb(main):002:0&gt; yourRubyChickens =  %w{ Chantecler RedShaver RhodeIslandRed }
=&gt; [&quot;Chantecler&quot;, &quot;RedShaver&quot;, &quot;RhodeIslandRed&quot;]
irb(main):003:0&gt; yourRubyChickens.length
=&gt; 3
irb(main):004:0&gt; yourRubyChickens.size
=&gt; 3
irb(main):005:0&gt; yourRubyChickens.count
=&gt; 3&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;But, beware of &lt;code class=&quot;language-text&quot;&gt;#count&lt;/code&gt; in Rails!&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;[1] pry(main)&gt; yourRailsChickens = Chicken.all
  Chicken Load (2.1ms)  SELECT &quot;chickens&quot;.* FROM &quot;chickens&quot;
=&gt; [#&amp;lt;ChanteclerChicken:0x007f98eafcd6d8
  id: 1,
  type: &quot;ChanteclerChicken&quot;,
  color: &quot;white&quot;,
  created_at: Thu, 07 May 2015 14:36:36 UTC +00:00,
  updated_at: Thu, 07 May 2015 14:36:36 UTC +00:00&gt;,
 #&amp;lt;RedShaverChicken:0x007f98e63a9428
  id: 2,
  type: &quot;RedShaverChicken&quot;,
  color: &quot;white&quot;,
  created_at: Thu, 07 May 2015 14:37:01 UTC +00:00,
  updated_at: Thu, 07 May 2015 14:37:01 UTC +00:00&gt;,
 #&amp;lt;RedShaverChicken:0x007f98e63a9248
  id: 3,
  type: &quot;RedShaverChicken&quot;,
  color: &quot;black&quot;,
  created_at: Thu, 07 May 2015 14:37:25 UTC +00:00,
  updated_at: Thu, 07 May 2015 14:37:25 UTC +00:00&gt;,
 #&amp;lt;RedShaverChicken:0x007f98e63a9068
  id: 4,
  type: &quot;RedShaverChicken&quot;,
  color: &quot;red&quot;,
  created_at: Thu, 07 May 2015 14:37:35 UTC +00:00,
  updated_at: Thu, 07 May 2015 14:37:35 UTC +00:00&gt;,
 #&amp;lt;RedShaverChicken:0x007f98e63a8e88
  id: 5,
  type: &quot;RedShaverChicken&quot;,
  color: &quot;white&quot;,
  created_at: Thu, 07 May 2015 14:37:53 UTC +00:00,
  updated_at: Thu, 07 May 2015 14:37:53 UTC +00:00&gt;]

[2] pry(main)&gt; yourRailsChickens.length
=&gt; 5
[3] pry(main)&gt; yourRailsChickens.size
=&gt; 5
[4] pry(main)&gt; yourRailsChickens.count
   (0.2ms)  SELECT COUNT(*) FROM &quot;chickens&quot;
=&gt; 5&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;#size&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;#length&lt;/code&gt; are largely equivalent, but &lt;code class=&quot;language-text&quot;&gt;#count&lt;/code&gt; issues an additional query to the database that can seriously damage performance for the unsuspecting developer.&lt;/p&gt;
&lt;p&gt;For more info, checkout the docs for &lt;a href=&quot;http://www.rubydoc.info/docs/rails/4.0.0/ActiveRecord/Calculations:count&quot;&gt;count&lt;/a&gt; and &lt;a href=&quot;http://www.rubydoc.info/docs/rails/4.0.0/ActiveRecord/Associations/CollectionAssociation:length&quot;&gt;length&lt;/a&gt;.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[local load balancing]]></title><description><![CDATA[You can mimic the end-user’s UI experience accurately enough by running application code locally, but what about the backend? Once your code…]]></description><link>http://katieleonard.ca/blog/2015/2015-04-21-local-load-balancing/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2015/2015-04-21-local-load-balancing/</guid><pubDate>Wed, 22 Apr 2015 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;You can mimic the end-user’s UI experience accurately enough by running application code locally, but what about the backend? Once your code is deployed to production, requests will be divided between dozens of servers. If there is variation in the code paths running on each server (like during a feature rollout, for example), it is useful to determine beforehand if there are any dangerous conflicts. Enter local load-balancing.&lt;/p&gt;
&lt;!--more--&gt;
&lt;p&gt;&lt;a href=&quot;http://nginx.org/en/&quot;&gt;NGiNX&lt;/a&gt; is load balancing software that distributes requests across multiple servers, and it’s easy to get running quickly.&lt;/p&gt;
&lt;h3&gt;Installation&lt;/h3&gt;
&lt;p&gt;You can download and compile from source at &lt;a href=&quot;http://nginx.org/en/download.html&quot;&gt;NGiNX.org&lt;/a&gt;, or use &lt;code class=&quot;language-text&quot;&gt;brew install nginx&lt;/code&gt; on MacOS-X.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;➜  api_playground  brew &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; nginx
&lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;.

The default port has been &lt;span class=&quot;token builtin class-name&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; /usr/local/etc/nginx/nginx.conf to &lt;span class=&quot;token number&quot;&gt;8080&lt;/span&gt; so that nginx can run without sudo.

To have launchd start nginx at login:
    &lt;span class=&quot;token function&quot;&gt;ln&lt;/span&gt; -sfv /usr/local/opt/nginx/*.plist ~/Library/LaunchAgents
Then to load nginx now:
    launchctl load ~/Library/LaunchAgents/homebrew.mxcl.nginx.plist
Or, &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; you don&apos;t want/need launchctl, you can just run:
    nginx&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Start the server with the command &lt;code class=&quot;language-text&quot;&gt;nginx&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;Configuration&lt;/h3&gt;
&lt;p&gt;Your NGiNX installation added a config file: &lt;code class=&quot;language-text&quot;&gt;/usr/local/etc/nginx/nginx.conf&lt;/code&gt;. It is mostly commented configuration examples, so you can simply replace the current &lt;code class=&quot;language-text&quot;&gt;server&lt;/code&gt; configuration block with this:&lt;/p&gt;
&lt;p&gt;/usr/local/etc/nginx/nginx.conf&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;upstream myapp1 {
  server localhost:3000;
  server localhost:3030; #add as many servers as you want here
}

server {
  listen 8080;
  server_name localhost;
  location / {
    proxy_pass http://myapp1;
  }
}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Reload your NGiNX server with &lt;code class=&quot;language-text&quot;&gt;nginx -s reload&lt;/code&gt;, and hit &lt;a href=&quot;localhost:8080&quot;&gt;localhost:8080&lt;/a&gt; to ensure you have configured it correctly.&lt;/p&gt;
&lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/fcdb4da74a4375bed480fe419462d3ea/6a6e9/welcome_nginx.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 39.87341772151899%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAIAAAB2/0i6AAAACXBIWXMAAAsTAAALEwEAmpwYAAABLUlEQVQY042P3U7CQBBG+/5P4403GlAwaqGAMdv967bFtpTutoihGNoy266BBDHohedi8iWTM5nPeh0NyHT89jjjAzt4cNQLDSh3MSaE4OOkJwih2EUIIRdjx3FG47EVLhbpvaNubTmcvdsIRqxVHxXAvmkAYLfbbTab8ojKi5gzSjnxhBC+H86tzpi22ZttNbkb9q6un2969tMzIXg6cfr9fhRFxpiu68wlnTGddQyHXZwuqPCY8DwhoijmnCHkKpXXdf15YFuWJQD8PGB9J5llwhOhHzDKGOPhfB74PE1jpaTMCiXXebFqmuZvOU1TSglnnHOPYIJd5LoJxnlRrNbrOpNmv798/SyviiJdLqWUSZJIKQGgqrqqMqe+3e/mZ1lrDRraVgOA1tr8gy/GtLqZhvmA1gAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;welcome nginx&quot; title=&quot;welcome nginx&quot; src=&quot;/static/fcdb4da74a4375bed480fe419462d3ea/f058b/welcome_nginx.png&quot; srcset=&quot;/static/fcdb4da74a4375bed480fe419462d3ea/c26ae/welcome_nginx.png 158w,
/static/fcdb4da74a4375bed480fe419462d3ea/6bdcf/welcome_nginx.png 315w,
/static/fcdb4da74a4375bed480fe419462d3ea/f058b/welcome_nginx.png 630w,
/static/fcdb4da74a4375bed480fe419462d3ea/6a6e9/welcome_nginx.png 826w&quot; sizes=&quot;(max-width: 630px) 100vw, 630px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
&lt;h3&gt;Start your servers&lt;/h3&gt;
&lt;p&gt;NGiNX is configured and listening on ports 3000 and 3030. Now we just have to connect some servers!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Server 1&lt;/strong&gt;: &lt;code class=&quot;language-text&quot;&gt;bundle exec rails server -p 3030&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Server 2&lt;/strong&gt;: &lt;code class=&quot;language-text&quot;&gt;bundle exec rails server -p 3000 --pid tmp/pids/server2.pid&lt;/code&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Pro-tip: The Rails server stores its process id in a temporary file (&lt;code class=&quot;language-text&quot;&gt;/tmp/pids/server.pid&lt;/code&gt;), and will complain if you start another server unless you specify a new temporary pid file.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Check your progress by hitting localhost:8080:&lt;/p&gt;
&lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/aec30f8259b7afe56d8447634ce2b47a/5c744/load_balancing.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 79.11392405063292%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAQCAIAAACZeshMAAAACXBIWXMAAAsTAAALEwEAmpwYAAADHUlEQVQoz12Ty2sbVxTG55/KJrT7BAJZB4xbsJOVQsgiBAIpeFUKWcSF0EIDTes4KSWGQMFWaGXFCNlxFEfBrR4jZx4a3Zk7d+Zq7tzHvK40c1vJBNr+Fmf3cc75vnM0MiVt2N63Gm3QPrAODv1DwzUwwgRGGOGG33g62ZrYwB7bAIAgCBAK4iUYY80yrNbH1qsPr7pe10osMzHwFIdReASPdtCLXbbr5BNVqWpWVbNKlUrNlVKqLMs8zzXDMCb2RIhkLmdKKVawE/9dC7c66N3EnxCP7J80n79+Xj+p73Z2t19v17v1xul+e9BOk0RDCH08OwMuAFP3jJ3pXO+DXoSjGMUYYdMxLn598cLGhbXv11Z/XL307aWrD69e2byyvnVdUKHFcewBj3ASFEFe5nM5nyIchgFEPqPMg17tWW31p9X17fVrj689+O3B3Rd3b/x84/OvPutaXU39l0IWvu/jMIQQMsocz6n9UFt5uLL2aO2LR1/WHtcuf3N5p71jjA1MsVZVVVmVlapKtahSShyGJCIY45jEEMObz27eenrr3i/3Vr5bedJ4sne6ZyFTKSWl/H9nWcggCDDGixqEtmff2bmz8evG/a37t7duD8yBUmpWSEopF1zjKfeE63EXZcjPkBPag78+jEb6aDTShzowAQNs5Iw6bge7GLjAdmzHccZjx3VdTUd63d1rms1DdHgcHDdh0/TMJBY0pH7gD9nwJXy5CTf/IL+LmDPOsizL0lQIsch5oPffj953em+dqVOoIqSh7/vj6fhteHzADo7okR7pKU2TKCEkYowuZFlWFAXnXJs4juu4MpPVvCxVaRGr5bSO4Zs+7GM8lWKWkiSmMRc8XTZkjJdleX5kGoSw1+sZjqGHQ4MbdmT/2Ts1ddMcGsPBUB/pg2HfWmACACCEaZqeW7sQSymzLJtXc6mkUirhSRiEhBISR4QQzlhMSBzH0XS6HJsXRZEuSLIs+xRVpaqqUkpRRj3XxRgj34+iKM9zznlyzlKQLRfO8/xf4k9wzl0XhIsL8wghQghCCKX0/A2FEJSyfMk/hv0NceBB3aHe/mwAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;load balancing&quot; title=&quot;load balancing&quot; src=&quot;/static/aec30f8259b7afe56d8447634ce2b47a/f058b/load_balancing.png&quot; srcset=&quot;/static/aec30f8259b7afe56d8447634ce2b47a/c26ae/load_balancing.png 158w,
/static/aec30f8259b7afe56d8447634ce2b47a/6bdcf/load_balancing.png 315w,
/static/aec30f8259b7afe56d8447634ce2b47a/f058b/load_balancing.png 630w,
/static/aec30f8259b7afe56d8447634ce2b47a/40601/load_balancing.png 945w,
/static/aec30f8259b7afe56d8447634ce2b47a/5c744/load_balancing.png 1206w&quot; sizes=&quot;(max-width: 630px) 100vw, 630px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
&lt;p&gt;Checkout the &lt;a href=&quot;http://nginx.org/en/docs/http/load_balancing.html&quot;&gt;docs&lt;/a&gt; for more examples of nginx configuration.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[what else you can do after code school]]></title><description><![CDATA[Learning to program at a code school is a great opportunity to acquire new skills, and to make your current skills relevant in tech…]]></description><link>http://katieleonard.ca/blog/2015/2015-04-16-what-else-you-can-do-after-code-school/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2015/2015-04-16-what-else-you-can-do-after-code-school/</guid><pubDate>Thu, 16 Apr 2015 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Learning to program at a code school is a great opportunity to acquire new skills, and to make your current skills relevant in tech. Becoming a software developer is the most common goal, but there is a wide variety of roles that technical people can play in software that aren’t about writing code. Whether you have left a job in customer service, teaching, or research, the skills you gained in your last career will help you fill a niche in your new one. Here are a few paths in tech that don’t involve writing software, but do require some experience with coding, frameworks, and methodologies.&lt;/p&gt;
&lt;!--more--&gt;
&lt;h3&gt;Product Manager&lt;/h3&gt;
&lt;h5&gt;Code School + Business Management&lt;/h5&gt;
&lt;p&gt;As a product manager (aka product owner), you decide what features to build by studying the market and learning your customers’ needs. The result of your research is a product road map and business strategy for the next year and beyond. Field experience is essential to making good business decisions.&lt;/p&gt;
&lt;h3&gt;Project Manager&lt;/h3&gt;
&lt;h5&gt;Code School + Project Management&lt;/h5&gt;
&lt;p&gt;A project manager follows the product road map feature by feature. In this role you will be responsible for marshalling resources and delivering product. Excellent communication skills are a must, as is a technical familiarity with the system under construction. You need to ask the right questions, identify risks, validate estimates, and eliminate blockers.&lt;/p&gt;
&lt;h3&gt;Engineering Manager&lt;/h3&gt;
&lt;h5&gt;Code School + Project Management + People Management&lt;/h5&gt;
&lt;p&gt;High-functioning teams do not manifest by chance — they are the result of deliberate choices made at the intersection of project needs, culture fit, and career growth. As an engineering manager, you don’t just assemble the team. You also schedule projects, implement (or remove) processes, grow careers, and communicate up and down the management chain. In addition to all of these tasks, you must be familiar with the job the team is performing.&lt;/p&gt;
&lt;h3&gt;Technical Writer&lt;/h3&gt;
&lt;h5&gt;Code School + Written Communication Skills&lt;/h5&gt;
&lt;p&gt;Writing technical specs and documentation will require all of your technical knowledge as well as language, teaching, and research skills. The technical writing field is expected to grow enormously in the next 10 years&lt;sup id=&quot;fnref-1&quot;&gt;&lt;a href=&quot;#fn-1&quot; class=&quot;footnote-ref&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;, and delivering web-based product support will be par for the course. Use your new coding skills to build documentation websites and forums, as well as generate useful content.&lt;/p&gt;
&lt;h3&gt;Technical Support&lt;/h3&gt;
&lt;h5&gt;Code School + Customer Service&lt;/h5&gt;
&lt;p&gt;Technical support is growing at a similar pace to technical writing. Helping users interact successfully with a product is essential to their happiness, and companies have a vested interest in troubleshooting where these interactions go wrong. You act as liaison between the end user and the development and management teams by reporting and triaging bugs, working with developers to resolve issues, and communicating with internal customers as well as external ones.&lt;/p&gt;
&lt;h3&gt;Quality Assurance Engineer&lt;/h3&gt;
&lt;h5&gt;Code School + Product Knowledge&lt;/h5&gt;
&lt;p&gt;As a QA engineer, you are a product expert, not a tester. You understand the way users interact with the product and how the features interact with each other. You can reveal blind spots in design and edge cases of user experience that will catch a feature engineer unawares. Combining attention to detail with a holistic view of the system, QA engineers ensure that users continue to trust the product you are delivering.&lt;/p&gt;
&lt;p&gt;Not everyone leaves code school with a passion for building software, but everyone does leave with the skills they need to have an awesome career in tech. No education or experience is wasted, so don’t forget to leverage your current skill set as you are learning a new one.&lt;/p&gt;
&lt;div class=&quot;footnotes&quot;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&quot;fn-1&quot;&gt;
&lt;p&gt;Bureau of Labour Statistics: &lt;a href=&quot;http://www.bls.gov/ooh/media-and-communication/technical-writers.htm&quot;&gt;Technical Writers&lt;/a&gt;&lt;/p&gt;
&lt;a href=&quot;#fnref-1&quot; class=&quot;footnote-backref&quot;&gt;↩&lt;/a&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</content:encoded></item><item><title><![CDATA[getting your foot in the door]]></title><description><![CDATA[Many people have asked me what it is like on the other side of code school, and if there is any advice I would give to someone before they…]]></description><link>http://katieleonard.ca/blog/2015/2015-04-12-get-your-foot-in-the-door/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2015/2015-04-12-get-your-foot-in-the-door/</guid><pubDate>Sun, 12 Apr 2015 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Many people have asked me what it is like on the other side of code school, and if there is any advice I would give to someone before they get their first programming job. Technical ability, problem solving, and communication skills are all essential to success as a developer, and your online presence is a way to demonstrate all three. Getting your foot in the door requires having something to show — keeping your foot in the door requires a little bit more.&lt;/p&gt;
&lt;!--more--&gt;
&lt;h3&gt;Have something to show&lt;/h3&gt;
&lt;p&gt;Not every developer spends every waking moment working on open source projects or inventing the next big framework. We all have lives, families, and other pursuits that take priority; however, experienced programmers likely have solid work-related contributions they can point to during an interview. First-timers need some proof that they can apply what they learn. Side projects show potential employers what you are learning, and that you are interested in programming, not just the salary it comes along with.&lt;/p&gt;
&lt;p&gt;Create a &lt;a href=&quot;https://github.com/&quot;&gt;GitHub&lt;/a&gt; account. If you are in code school, you are likely already working towards a portfolio of apps and widgets to show off during an interview. If you are considering code school, this is something you should not wait to do. When you work through a tutorial, commit it to GitHub, give it a README, and include what you are working through and why.&lt;/p&gt;
&lt;h3&gt;Start filling your toolbox&lt;/h3&gt;
&lt;p&gt;You can usually assemble a piece of Ikea furniture with only an allen key, but what about that desk drawer that suddenly calls for a screwdriver? Completing the task requires the right tools for the job, and your ability to solve a programming problem is no different. Git, Chrome Developer Tools, and Pry are part of the the Swiss Army knife for any web developer.
&lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/261602506d935c6d15f142c3843f6c89/4b190/toolbox.jpg&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 100%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAUABQDASIAAhEBAxEB/8QAGAABAAMBAAAAAAAAAAAAAAAAAAECAwX/xAAXAQADAQAAAAAAAAAAAAAAAAAAAgMB/9oADAMBAAIQAxAAAAHsVxxg/QVVS0ASNP/EAB0QAAEDBQEAAAAAAAAAAAAAAAEAEBECAxIxMkH/2gAIAQEAAQUCJWTXd+U8woDf/8QAFxEAAwEAAAAAAAAAAAAAAAAAARESIP/aAAgBAwEBPwGCsf/EABkRAQACAwAAAAAAAAAAAAAAAAEAEQIDEP/aAAgBAgEBPwF3YjTBslHP/8QAGBAAAwEBAAAAAAAAAAAAAAAAABARATH/2gAIAQEABj8CcIYuL//EAB4QAQACAQQDAAAAAAAAAAAAAAEAERAhMVFhQZGh/9oACAEBAAE/IaEgatSucakvJE46uzqfNEO4Toesf//aAAwDAQACAAMAAAAQzzf+/8QAFxEBAQEBAAAAAAAAAAAAAAAAAREAEP/aAAgBAwEBPxAajJGavP/EABoRAAICAwAAAAAAAAAAAAAAAAARARAxQVH/2gAIAQIBAT8QYDAonozVf//EAB0QAQACAgIDAAAAAAAAAAAAAAEAETFBEFFxkfH/2gAIAQEAAT8QEylN3biWVf0x5giWInZCEBAv3AWAaDDo4hK1PaT5KABQAGif/9k=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;Fill your toolbox&quot; title=&quot;Fill your toolbox&quot; src=&quot;/static/261602506d935c6d15f142c3843f6c89/828fb/toolbox.jpg&quot; srcset=&quot;/static/261602506d935c6d15f142c3843f6c89/ff44c/toolbox.jpg 158w,
/static/261602506d935c6d15f142c3843f6c89/a6688/toolbox.jpg 315w,
/static/261602506d935c6d15f142c3843f6c89/828fb/toolbox.jpg 630w,
/static/261602506d935c6d15f142c3843f6c89/4b190/toolbox.jpg 800w&quot; sizes=&quot;(max-width: 630px) 100vw, 630px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://git-scm.com/&quot;&gt;&lt;strong&gt;Git&lt;/strong&gt;&lt;/a&gt; is like “track changes” for source code. The docs describe it as a series of snapshots of your code base. “Every time you commit, or save the state of your project in Git, it basically takes a picture of what all your files look like at that moment and stores a reference to [it][^1].” Source control allows you to work in the same code base with other developers and not step on one another’s toes. Start with &lt;a href=&quot;http://gitimmersion.com/&quot;&gt;Git Immersion&lt;/a&gt; for some practical experience.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.chrome.com/devtools&quot;&gt;&lt;strong&gt;Chrome Developer Tools&lt;/strong&gt;&lt;/a&gt; give you access to everything that happens to your application when it is sent to the browser. Troubleshoot Javascript, CSS, and layout issues without having to refresh the page. Check out the tutorials at &lt;a href=&quot;http://discover-devtools.codeschool.com/&quot;&gt;discover-devtools&lt;/a&gt; by CodeSchool.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/pry/pry&quot;&gt;&lt;strong&gt;Pry&lt;/strong&gt;&lt;/a&gt; gives you an interactive debugging session wherever you put a breakpoint in a Rails application. &lt;code class=&quot;language-text&quot;&gt;binding.pry&lt;/code&gt; throws you down the rabbit hole into the inner workings of your program’s psyche. Check out &lt;a href=&quot;http://katieleonard.ca/blog/2015/exploring-the-stack/&quot;&gt;exploring the stack&lt;/a&gt; for more details about this powerful tool.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Use the docs&lt;/strong&gt;. Knowing how to find and navigate documentation is more important than remembering how to do File I/O. If you find yourself in a technical interview where they don’t let you search the web for help, share your thought process, imagine the solution you might have found had you performed the search, and work your way through the problem with pseudocode. Experienced developers use Google search and StackOverflow constantly, so pop that error message into the search bar to see what turns up. A word to the wise: if an answer was posted more than two years ago, it may no longer be relevant.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Get to know your community&lt;/h3&gt;
&lt;p&gt;Your next job in programming is more likely to come from someone in your network than from hitting the street with your resume. If you can claim an acquaintance with someone from a company you want to work for, that is one more point in your favour.&lt;/p&gt;
&lt;p&gt;Go to meetups. If you are shy about meeting lots of new people at once, try introducing yourself to the invited speakers at the end — they are usually well connected and respected in the community. If you approach them with your name and a question or comment about their talk, they are likely to remember you.&lt;/p&gt;
&lt;h3&gt;Do scary things&lt;/h3&gt;
&lt;p&gt;Not like skydiving, or alligator wrestling. Write blogs, contribute to open source projects, start &lt;a href=&quot;http://createyourproglang.com/&quot;&gt;your own programming language&lt;/a&gt;, or become visible on social media. You don’t need to be an expert to have an opinion. Don’t stop taking risks after you land your first job, either.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Find an area of your work that people are avoiding and become an expert. You will be known as the person who can do that thing we all hate, and your colleagues will value your expertise.&lt;/li&gt;
&lt;li&gt;Take the hardest ticket from the top of the stack. Don’t sift through them until you find something you think you know how to do. Your best opportunity to stretch your skills is to do something scary and uncomfortable.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I work with a lot of people who don’t have formal computer science degrees, and while their backgrounds vary, they all share a love of problem solving and a willingness to work hard. Take responsibility for your own learning — code school will only bring you so far, and the rest is up to you.&lt;/p&gt;
&lt;div class=&quot;footnotes&quot;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&quot;fn-1&quot;&gt;
&lt;p&gt;&lt;a href=&quot;http://git-scm.com/book/en/v2/Getting-Started-Git-Basics&quot;&gt;Getting started with git&lt;/a&gt;&lt;/p&gt;
&lt;a href=&quot;#fnref-1&quot; class=&quot;footnote-backref&quot;&gt;↩&lt;/a&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</content:encoded></item><item><title><![CDATA[What's it like to be a developer?]]></title><description><![CDATA[My manager has invited me to help her give a talk to students in a Web Development program. I have been working in the field for about 1…]]></description><link>http://katieleonard.ca/blog/2015/2015-04-11-what-is-it-like-to-be-a-programmer/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2015/2015-04-11-what-is-it-like-to-be-a-programmer/</guid><pubDate>Sat, 11 Apr 2015 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;My manager has invited me to help her give a talk to students in a Web Development program. I have been working in the field for about 18 months, and a lot of the uncertainty is still fresh in my mind: what is it like to be a programmer? How can I get a job as a junior? What can I do now that will help me in my first job? I didn’t know many people in the industry, and was unaware of the vast meetup community&lt;sup id=&quot;fnref-1&quot;&gt;&lt;a href=&quot;#fn-1&quot; class=&quot;footnote-ref&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;. Answers to these questions were difficult to find online, so over the next few posts I will make an attempt.&lt;/p&gt;
&lt;!--more--&gt;
&lt;hr&gt;
&lt;h3&gt;Meetings: Important communication tools.&lt;/h3&gt;
&lt;p&gt;Programming is mostly about decision making, and not all decisions can be made alone. Questions like, what technologies to use, how you should spend your time, and how to scale, require meetings with managers and other teams.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Sprint planning&lt;/strong&gt; is a weekly meeting where the team gets together with managers to prioritize tasks for the week. You look back on last week, and either carry over tasks you didn’t accomplish, or re-prioritize based on what has arisen in the meantime.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Standups&lt;/strong&gt; happen daily, and should only last around 10 minutes. You each take a turn sharing what you worked on yesterday, what you are working on today, and whether you are blocked by anything. It is important to speak up when you are stuck! Sharing your blockers will usually result in help; someone may have encountered this problem before, have a new approach to suggest, or have insider information that can get you to a solution.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Demos&lt;/strong&gt; will happen on a weekly or bi-weekly basis, and are an opportunity to share your accomplishments. While many stakeholders are involved in the project and sprint planning, they are often disconnected from the work as it is being performed. Regular demos help to keep them in the loop, and are an opportunity to explain both progress and unexpected delays.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Code reviews&lt;/strong&gt; can be formal or informal, and allow your team to gain consensus on style, design, performance, and testing. Your code design decisions will have an impact on the project as a whole, so it never hurts to get feedback from a teammate before you ship it. Readability is more important than cleverness, and is a kindness to future maintainers.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A portion of your week will always be spent in meetings. Try to identify when your most productive hours are in the day, and keep that time free. For example, if you lump meetings around lunch (none before 11am or after 2pm) you have a solid chunk of time in the morning and the afternoon to focus effectively.&lt;/p&gt;
&lt;h3&gt;Stories: How big ideas are turned into actions.&lt;/h3&gt;
&lt;p&gt;An idea like “improve the user’s experience of widget B” is a goal, not a task. It can be broken down into &lt;strong&gt;stories&lt;/strong&gt; such as: &lt;em&gt;identify the problem&lt;/em&gt;, &lt;em&gt;brainstorm solutions&lt;/em&gt;, &lt;em&gt;design the new widget&lt;/em&gt;, and &lt;em&gt;implement the new widget&lt;/em&gt;. Each of these stories are actionable: there is a clear path from start to finish. Use the &lt;a href=&quot;http://en.wikipedia.org/wiki/Single_responsibility_principle&quot;&gt;single-responsibility principle&lt;/a&gt; in your stories as well as in your code: if you use the word AND to describe the task, that is a hint that you should have two stories instead of one. Most companies will use a task management, or &lt;strong&gt;ticket&lt;/strong&gt; system such as Pivotal Tracker or Jira, where you can see what work is assigned to you, and where managers can check in on your progress.&lt;/p&gt;
&lt;h3&gt;Feature Work: What should be built?&lt;/h3&gt;
&lt;p&gt;Product managers have their eye on the market. They know what features our customers want, and they know what our competitors offer. A product manager will build a product road-map with a long schedule (think months and years, not weeks). The team will sit down with the feature requirements and a first-draft design, break it down into stories, and estimate the time/complexity of each story. Managers then apportion those estimates into chunks of work — in &lt;strong&gt;Agile&lt;/strong&gt;, these chunks are laid out in &lt;strong&gt;sprints&lt;sup id=&quot;fnref-2&quot;&gt;&lt;a href=&quot;#fn-2&quot; class=&quot;footnote-ref&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Defining work in this way lets you identify what can be done in parallel and what needs to be in place before the next task can be accomplished. It also gives project managers the information they need to make decisions about what to sacrifice in order to meet a deadline. If the project is over the time budget, and gold-plated widget A needs features 1, 2, and 3, then maybe you can ship the widget with only 1 and 2, but save 3 for later. Sometimes you have to compromise on feature completeness just to get it out the door.&lt;/p&gt;
&lt;h3&gt;Troubleshooting and Maintenance: Detective work.&lt;/h3&gt;
&lt;p&gt;Finding a bug is like being a detective: you gather clues, follow leads, and occasionally end up lost in a blind alley. A single line of code can hold multiple bugs (Pro tip: watch out for Regexes&lt;sup id=&quot;fnref-3&quot;&gt;&lt;a href=&quot;#fn-3&quot; class=&quot;footnote-ref&quot;&gt;3&lt;/a&gt;&lt;/sup&gt; — they are a great place for bugs to hide). In a code base with hundreds of thousands of lines, you will inevitably spend more time hunting and fixing bugs than writing new code.&lt;/p&gt;
&lt;h3&gt;Deploying code: Sending it into the wild.&lt;/h3&gt;
&lt;p&gt;Running an application in production is not the same as running it on your computer. Your application may need to serve thousands of requests per second, and a single instance running on a single server won’t cut it. There is a whole stack of management software that you would do well to be familiar with, and having at least a passing familiarity with &lt;a href=&quot;https://jenkins-ci.org/&quot;&gt;Jenkins&lt;/a&gt;, &lt;a href=&quot;http://capistranorb.com/&quot;&gt;Capistrano&lt;/a&gt;, and &lt;a href=&quot;http://tldp.org/HOWTO/Bash-Prog-Intro-HOWTO.html&quot;&gt;bash scripting&lt;/a&gt; will help you when it is your turn to carry the pager.&lt;/p&gt;
&lt;h3&gt;Pager duty: Evil alarm clock.&lt;/h3&gt;
&lt;p&gt;When you write software that your customers use around the clock, you have to be there when things break, no matter what time. Most companies will institute a rotation to share the burden of vigilence around the team. Having great documentation about what to do in an emergency is essential to finding a clear path of action at 3am. As with anything, the more you prepare, the higher your confidence level will be.&lt;/p&gt;
&lt;p&gt;The job is far from routine because of the diverse set of problems to solve. I have become comfortable grabbing a story without already knowing the answer, partly from knowing that if I get stuck I am no more than a “Hey Bryan,” or “Hey KWu,” away from someone who wants to help, even if it is at 3am (thanks again, Vince!).&lt;/p&gt;
&lt;div class=&quot;footnotes&quot;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&quot;fn-1&quot;&gt;
&lt;p&gt;If you are in Portland, Oregon, checkout &lt;a href=&quot;http://calagator.org/&quot;&gt;Calagator&lt;/a&gt;. Otherwise, try &lt;a href=&quot;http://www.meetup.com/&quot;&gt;Meetup.com&lt;/a&gt;&lt;/p&gt;
&lt;a href=&quot;#fnref-1&quot; class=&quot;footnote-backref&quot;&gt;↩&lt;/a&gt;
&lt;/li&gt;
&lt;li id=&quot;fn-2&quot;&gt;
&lt;p&gt;Read more about &lt;a href=&quot;http://en.wikipedia.org/wiki/Agile_software_development&quot;&gt;Agile methodology&lt;/a&gt;&lt;/p&gt;
&lt;a href=&quot;#fnref-2&quot; class=&quot;footnote-backref&quot;&gt;↩&lt;/a&gt;
&lt;/li&gt;
&lt;li id=&quot;fn-3&quot;&gt;
&lt;p&gt;Regex (short for regular expression) is a search pattern based on a sequence of characters.&lt;/p&gt;
&lt;a href=&quot;#fnref-3&quot; class=&quot;footnote-backref&quot;&gt;↩&lt;/a&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</content:encoded></item><item><title><![CDATA[exploring the stack]]></title><description><![CDATA[Another brilliant Rails troubleshooting technique I have recently added to my toolbox is  as an add-on to . 1. Add  and  to the development…]]></description><link>http://katieleonard.ca/blog/2015/2015-03-25-exploring-the-stack/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2015/2015-03-25-exploring-the-stack/</guid><pubDate>Wed, 25 Mar 2015 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Another brilliant Rails troubleshooting technique I have recently added to my toolbox is &lt;a href=&quot;https://github.com/pry/pry-stack_explorer&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;pry-stack_explorer&lt;/code&gt;&lt;/a&gt; as an add-on to &lt;a href=&quot;https://github.com/pry/pry&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;pry&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h4&gt;1. Add &lt;code class=&quot;language-text&quot;&gt;pry&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;pry-stack_explorer&lt;/code&gt; to the development/test group of your gemfile:&lt;/h4&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ruby&quot;&gt;&lt;pre class=&quot;language-ruby&quot;&gt;&lt;code class=&quot;language-ruby&quot;&gt;group &lt;span class=&quot;token symbol&quot;&gt;:test&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token symbol&quot;&gt;:development&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;do&lt;/span&gt;
  gem &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&apos;pry&apos;&lt;/span&gt;&lt;/span&gt;
  gem &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&apos;pry-stack_explorer&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h4&gt;2. Add a binding pry anywhere in your code&lt;/h4&gt;
&lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/afc9dcebe185d831c93bbf58947295f5/5a190/binding-pry.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 27.848101265822784%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAGCAIAAABM9SnKAAAACXBIWXMAAAsTAAALEwEAmpwYAAAA10lEQVQY043NzUoDMRQF4DyvA4JL+xY+gUuXMm/hQlRcWIbaGdNJmjSZTP4stsy9uWJRNzLgtziLA4fD4OUZXpu27ZRShWgCRMRygogAMP2AbwgT4KlnUpshRu/s4JwW3ZavhNxKIUUvjDFKKa21Vl+stc65lNIwDDEEaw3zaTwA7D8o5wOtb+5ur87OLxaLy6qq6romIkSkGWw3+nWzerhvm6clPF7HzVILuRO9MSbnTESllN/8Mw7hGPTkR4zumPYQYgm+vGf6B8Z7zvuNdWP3xuce5safll9SCrqZwUYAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;binding pry&quot; title=&quot;binding pry&quot; src=&quot;/static/afc9dcebe185d831c93bbf58947295f5/f058b/binding-pry.png&quot; srcset=&quot;/static/afc9dcebe185d831c93bbf58947295f5/c26ae/binding-pry.png 158w,
/static/afc9dcebe185d831c93bbf58947295f5/6bdcf/binding-pry.png 315w,
/static/afc9dcebe185d831c93bbf58947295f5/f058b/binding-pry.png 630w,
/static/afc9dcebe185d831c93bbf58947295f5/5a190/binding-pry.png 800w&quot; sizes=&quot;(max-width: 630px) 100vw, 630px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
&lt;h4&gt;3. Enter &lt;code class=&quot;language-text&quot;&gt;show-stack&lt;/code&gt; at the pry prompt&lt;/h4&gt;
&lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/c4b89dded3db38d8fd6ea446da4ec572/764be/show-stack.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 55.06329113924051%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAIAAADwazoUAAAACXBIWXMAAAsTAAALEwEAmpwYAAACGklEQVQoz12QS2sTUQBG5ze7sEhVaH3QCi6qCAriRly4EFqtBhTd2Ig0k95k3mmTTif3Mfc5c+/NJDQzaUfautGzPwe+zzHzhdSGSalnVWGMsHMr0tZ/3t1/vb7x8NHW1v3NBwCAtm0vLi7af3Hq7LSepktKGoIamDU5WeG0nRyw3nfwtZP8+hn++FYK0bbt5eXl/3IluWVMM6opFWiqMJaY0Fy8w1/eJO+fbj9+srnxbGdnsVg0TVPX9Wq1quu6Xl7hQISGQ8/t9+PR6AgAt3/kDf2u+/te8Optf29v9+On/c+dTmc4HEwmk1ESR2Hke8Ner+d5npOmp77nAXCEIByfnGRn2dkkjU6Sl2xv+8OLO7dur99dX1tbO+h26+VSXyOEKMtSCOHoUnPOIYTWWMY4zamUkhKaTtMshwQTiCAhhGCMEUYIcS4YY0qp8/NzZzFfhEF4eHgIIQqCMI7iKIp8z0+iaAAGbs8dABCFoed5x8fHAwACP0jTU4RQXTdOTkjg+67rIoTiOB6Px0EQZNk0jqJkNMIIU0oZYxhjzjlCCEI4zTIIEc2pwxgjGEMIZzNLKdVlmec5wURKiTGWUnIuOOeEECmkUopdY4zhnDlKKc45pbSqKsHFzR9/l1OKMRLiSmaMCSEZZYRcpW8SDpzCJElyms/nc621Umo2mxVFIYQw1hpri7K01hpjlFKFKnSpi6KQUlZV9Qc37EEL+FjcFwAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;show stack&quot; title=&quot;show stack&quot; src=&quot;/static/c4b89dded3db38d8fd6ea446da4ec572/f058b/show-stack.png&quot; srcset=&quot;/static/c4b89dded3db38d8fd6ea446da4ec572/c26ae/show-stack.png 158w,
/static/c4b89dded3db38d8fd6ea446da4ec572/6bdcf/show-stack.png 315w,
/static/c4b89dded3db38d8fd6ea446da4ec572/f058b/show-stack.png 630w,
/static/c4b89dded3db38d8fd6ea446da4ec572/764be/show-stack.png 806w&quot; sizes=&quot;(max-width: 630px) 100vw, 630px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
&lt;h4&gt;4. Enter &lt;code class=&quot;language-text&quot;&gt;up&lt;/code&gt; or &lt;code class=&quot;language-text&quot;&gt;down&lt;/code&gt; to explore the state of the stack&lt;/h4&gt;
&lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/8a98c1223b825a055a9b4f8717ef9472/3534c/travel-the-stack.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 119.62025316455697%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAYCAIAAAB1KUohAAAACXBIWXMAAAsTAAALEwEAmpwYAAADT0lEQVQ4y4WUy47lNBCG8+w8Aw8wGzYsWIMQswEGxEjTo+k+11xsJ47jXBzf7dyDnEYshtPik2UlJZVUVf7/ikxyYbigdd02tKYVIYQe1HXdtl1NKakCZYkppV3bdYwJzvu+J6SKlFRt16rBc7lIs6z7vm77Fu5tXdflYD3Yjsh+sB1E1vqaGZKDy+cE3IvVms25Rat1HPf/IxqGqe6VMe2i5arkrJWVbBFidX7ftn1e9mXdxjnU89/knvO2Z7RppFLW+W/LH941Pw5czL+dxg+n6dfn6f3n6eNt2x4lj/F5vXxZri8Y467tqpndXb4v267sKswm7MbU7h+3EC0onTASuCgJ6RnzyjlphJRSa+OcMloaLaRUMsSEOD6lUkpJISJwekZperrdnj4F0jQFAGRZBgHIUY4gTJI0TVKQZQhCCGBeFCXGSZJAACLGRdv2uCgQQqQkRhshuNbaWRumoPQ0Tq9v83DaI2O6KPKK0rIsIYBZliGEMC6NNr3iyus3n4p1Heu6pq57xjAualrTQ1VW6tp23+TvfmYf30yejmmv1xdCCOfiqwozR+jUh+DD5BHEI0ZdkZOK8EO0UgrOQ9taKaeM7GXfc61VCCqtlNJaG22UklFf4pbWsMgRKkpSkeOgokB5XuASIXS5XrM0q6pKaeWsMcZ4551zztpomtcEWO7YNW7Ol1xQ0uNCENJBVKteaNUz9mbPzvmnZzkM0/12O51O1+dnCqGkVDVNLzouuJJKCDE+8knk/PDlRbW2wT3kjHMhhFLaGOedtc47773Xzk7L/CB5nteXqyUck6bgjEspjdZSSu/8v+7dxznI243hHqZwB+PvEVe6ZroWTGttjeEHRulOse/oT3/K07Ys05ds/BSPf5zD+T24bTusEmkQOxDb9E4Jqet6GAZjzOgH5fT39Je/xHnf9pD8/mm85bO2c82XXv1T9pbd9+SywIRUlZTyK5G8rptlmGbjlmkO6ykI5nUjrVFzO9Miv2fgcjlfL5f4Hif3+H6Pg28gBCCL4ziJk+yVJIUAFhDFcZylaXRYrIQQ3q7XJEn0gdHaWiuDd4OevPfW2iEM3g8H7viNvB/aVgOQFQUuyzJHKE3THKES47BmGXPOvSWSvwFy6kWF3F3vuQAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;travel the stack&quot; title=&quot;travel the stack&quot; src=&quot;/static/8a98c1223b825a055a9b4f8717ef9472/f058b/travel-the-stack.png&quot; srcset=&quot;/static/8a98c1223b825a055a9b4f8717ef9472/c26ae/travel-the-stack.png 158w,
/static/8a98c1223b825a055a9b4f8717ef9472/6bdcf/travel-the-stack.png 315w,
/static/8a98c1223b825a055a9b4f8717ef9472/f058b/travel-the-stack.png 630w,
/static/8a98c1223b825a055a9b4f8717ef9472/3534c/travel-the-stack.png 808w&quot; sizes=&quot;(max-width: 630px) 100vw, 630px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
&lt;h4&gt;Other goodies&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Pass a string to &lt;code class=&quot;language-text&quot;&gt;up&lt;/code&gt; or &lt;code class=&quot;language-text&quot;&gt;down&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;pry-stack_explorer&lt;/code&gt; will jump to the first frame that matches:&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;Frame number: &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/108

From: /Users/keighty/Documents/projects/api_playground/app/models/user.rb @ line &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt; User&lt;span class=&quot;token comment&quot;&gt;#full_name:&lt;/span&gt;

    &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;: def full_name
 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;:   binding.pry
    &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;:   &lt;span class=&quot;token string&quot;&gt;&quot;#{first_name} #{last_name}&quot;&lt;/span&gt;
    &lt;span class=&quot;token number&quot;&gt;6&lt;/span&gt;: end

&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; pry&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;User&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; up instrument

Frame number: &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;/108
Frame type: method

From: /usr/local/var/rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/activesupport-4.2.0/lib/active_support/notifications.rb @ line &lt;span class=&quot;token number&quot;&gt;166&lt;/span&gt; ActiveSupport::Notifications.instrument:

    &lt;span class=&quot;token number&quot;&gt;162&lt;/span&gt;: def instrument&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;name, payload &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token number&quot;&gt;163&lt;/span&gt;:   &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; notifier.listening?&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token number&quot;&gt;164&lt;/span&gt;:     instrumenter.instrument&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;name, payload&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; yield payload &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; block_given? &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token number&quot;&gt;165&lt;/span&gt;:   &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt;
 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;166&lt;/span&gt;:     yield payload &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; block_given?
    &lt;span class=&quot;token number&quot;&gt;167&lt;/span&gt;:   end
    &lt;span class=&quot;token number&quot;&gt;168&lt;/span&gt;: end

&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; pry&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ActiveSupport::Notifications&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; down view

Frame number: &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;/108
Frame type: method

From: /Users/keighty/Documents/projects/api_playground/app/views/greetings/hello.html.erb @ line &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; ActionView::CompiledTemplates&lt;span class=&quot;token comment&quot;&gt;#_app_views_greetings_hello_html_erb___3157151947187763552_70316982999600:&lt;/span&gt;

 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;: &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;h&lt;span class=&quot;token operator&quot;&gt;&lt;span class=&quot;token file-descriptor important&quot;&gt;1&lt;/span&gt;&gt;&lt;/span&gt;Greetings, &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;%&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; @person.full_name %&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;/h&lt;span class=&quot;token operator&quot;&gt;&lt;span class=&quot;token file-descriptor important&quot;&gt;1&lt;/span&gt;&gt;&lt;/span&gt;
    &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;: &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;p&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;This is a greetings view&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;/p&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Pass an integer to &lt;code class=&quot;language-text&quot;&gt;up&lt;/code&gt; or &lt;code class=&quot;language-text&quot;&gt;down&lt;/code&gt; to leap over frames&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; pry&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Class:0x007fe7eb82133&lt;span class=&quot;token operator&quot;&gt;&lt;span class=&quot;token file-descriptor important&quot;&gt;0&lt;/span&gt;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; up &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;

Frame number: &lt;span class=&quot;token number&quot;&gt;6&lt;/span&gt;/108
Frame type: block

From: /usr/local/var/rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/actionview-4.2.0/lib/action_view/renderer/template_renderer.rb @ line &lt;span class=&quot;token number&quot;&gt;54&lt;/span&gt; ActionView::TemplateRenderer&lt;span class=&quot;token comment&quot;&gt;#render_template:&lt;/span&gt;

    &lt;span class=&quot;token number&quot;&gt;49&lt;/span&gt;: def render_template&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;template, layout_name &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; nil, locals &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; nil&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;#:nodoc:&lt;/span&gt;
    &lt;span class=&quot;token number&quot;&gt;50&lt;/span&gt;:   view, locals &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; @view, locals &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token number&quot;&gt;51&lt;/span&gt;:
    &lt;span class=&quot;token number&quot;&gt;52&lt;/span&gt;:   render_with_layout&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;layout_name, locals&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt;layout&lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt;
    &lt;span class=&quot;token number&quot;&gt;53&lt;/span&gt;:     instrument&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;:template, :identifier &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; template.identifier, :layout &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; layout.try&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;:virtual_path&lt;span class=&quot;token punctuation&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;do&lt;/span&gt;
 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;54&lt;/span&gt;:       template.render&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;view, locals&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt;*name&lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; view._layout_for&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;*name&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token number&quot;&gt;55&lt;/span&gt;:     end
    &lt;span class=&quot;token number&quot;&gt;56&lt;/span&gt;:   end
    &lt;span class=&quot;token number&quot;&gt;57&lt;/span&gt;: end

&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;9&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; pry&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;ActionView::TemplateRenderer&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; down &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;

Frame number: &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;/108
Frame type: method

From: /usr/local/var/rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/actionview-4.2.0/lib/action_view/template.rb @ line &lt;span class=&quot;token number&quot;&gt;333&lt;/span&gt; ActionView::Template&lt;span class=&quot;token comment&quot;&gt;#instrument:&lt;/span&gt;

    &lt;span class=&quot;token number&quot;&gt;331&lt;/span&gt;: def instrument&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;action, &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;block&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token number&quot;&gt;332&lt;/span&gt;:   payload &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; virtual_path: @virtual_path, identifier: @identifier &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;333&lt;/span&gt;:   ActiveSupport::Notifications.instrument&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;#{action}.action_view&quot;&lt;/span&gt;, payload, &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;block&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token number&quot;&gt;334&lt;/span&gt;: end&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;To learn even more awesome ways to use &lt;code class=&quot;language-text&quot;&gt;pry&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;pry-stack_explorer&lt;/code&gt;, check out the docs:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/pry/pry&quot;&gt;github.com/pry/pry&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/pry/pry-stack_explorer&quot;&gt;github.com/pry/pry-stack_explorer&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[troubleshooting nested scopes in angular]]></title><description><![CDATA[Many beginner Angular tutorials start with a set of canned data, an input field, and a search filter, so it was a natural place to start on…]]></description><link>http://katieleonard.ca/blog/2015/2015-03-10-troubleshooting-nested-scopes-in-angular/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2015/2015-03-10-troubleshooting-nested-scopes-in-angular/</guid><pubDate>Wed, 11 Mar 2015 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Many beginner Angular tutorials start with a set of canned data, an input field, and a search filter, so it was a natural place to start on my side project, Virtual Playbill. With even a small data set, watching the DOM change based on search criteria was a thrilling achievement. In the intervening months, as features were added, rebuilt, or taken away, I had inadvertently broken the search box. The tutorials were still available, and still fairly basic, but I couldn’t get it to work. Not until I found a couple of invaluable tools for troubleshooting overlapping scopes: &lt;!--more--&gt;&lt;/p&gt;
&lt;h4&gt;1. Use the developer tools console&lt;/h4&gt;
&lt;p&gt;This handy trick will give you a console object corresponding to that element’s scope:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;select a DOM element in using the chrome developer tools&lt;/li&gt;
&lt;li&gt;enter &lt;code class=&quot;language-text&quot;&gt;angular.element($0).scope()&lt;/code&gt; into the console pane (&lt;code class=&quot;language-text&quot;&gt;$0&lt;/code&gt; is a global variable holding a reference to the selected DOM element)&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// with the search box selected&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; angular&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;element&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;$0&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;scope&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

$get&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;h&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;$&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;a&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;$$ChildScope&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;$$ChildScope &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token literal-property property&quot;&gt;$$childTail&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;$$childHead&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;$$nextSibling&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; $get&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;h&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;$&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;a&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;$$ChildScope&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;$$ChildScope&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;$parent&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; h
  &lt;span class=&quot;token literal-property property&quot;&gt;playbillRows&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Array&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;23&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;playbills&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Array&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;68&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;search&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Object
    &lt;span class=&quot;token literal-property property&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;this is search text&quot;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// with the playbill area selected&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; angular&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;element&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;$0&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;scope&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

$get&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;h&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;$&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;a&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;$$ChildScope&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;$$ChildScope &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;$$childTail&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; $get&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;h&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;$&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;a&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;$$ChildScope&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;$$ChildScope&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;$$childHead&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; $get&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;h&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;$&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;a&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;$$ChildScope&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;$$ChildScope&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;$$nextSibling&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;$parent&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; h
  &lt;span class=&quot;token literal-property property&quot;&gt;playbillRows&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Array&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;23&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;playbills&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Array&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;68&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Things are definitely looking different between the scope containing my search box and the scope where I am laying out the view: the second scope appears to be a sibling of the first. I needed something a little more visual before it completely sunk in, though.&lt;/p&gt;
&lt;h4&gt;2. Use &lt;a href=&quot;https://chrome.google.com/webstore/detail/ng-inspector-for-angularj/aadgmnobpdmgmigaicncghmmoeflnamj&quot;&gt;ng-inspector&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;ng-inpector is a browser extension that allows you to navigate your angular app as if it were a file directory:&lt;/p&gt;
&lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 384px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/7330522354932cb903232b24e472b9c4/804b2/vp_ng_inspector.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 96.20253164556962%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAATCAIAAAAf7rriAAAACXBIWXMAAAsTAAALEwEAmpwYAAADCElEQVQ4y3WSy27bRhhG9RrddNWd6wYB5FVde2mkr9BH8HtkUaBGGsNON0UXBQpfBHjVGDC8yK5yKleURMuyLiRlkRxyOLxf5sKZYUEpQWwjOYvBgMSZwXzf3xjdDq+vO+2rK0VRbACcJwD70xaAOI6rBzSmk7GidAcDdaAOfN8PPxGEURwmRRAECCHf9xFCaZpKKYUQUspa9r1orFppGkdR5HkeQijPc0oJoSVJEHGHjLHqCzSSJLPvIYQfzkYeimriJA6xesx7f4wuDn/+5dX+619fLTk8PDw4OFgsFivZWWjImOoudGYzzdD1uaGNddu9bvHubxWzL/Z+eva8+eOLF1tbW9vb2zs7OxsbG+fn57VMCiMrhDqGrgsBsMMgLLJUVlXZ2S9//5b0/ozu+6btWpbZVZTJZAKWoQohljLJMRWDOwhsACGM45gSXFUVwyn27/kymBVJklBKH72ZUVYQ3h060+nsRlX7/d5kOrYtp8iL+r+U1dJnrFwsFkVRPJYZxZSPtDotAEDgB1mWUUoFLytRVh9v5ly4rksIeSrnuLzq2bPZdHhzY5pWGER1jfWVQlaVEIJzjjHWdT1JYiklXyKEaOQ4t+bImtse8izLArZtmqZtWRhjyhhNYMnoF3vOssyxfNt0kY8AcFzoOsslp4JOL2h7D3X+arVaR0dHx8fHp6enrVbr7Ozs5OSk3+838iKb3dr6ZM4Fl6IePcF5KSSJAWvvVdjV37787puvnj1v/rD5fbPZXFtb29zcXF9f393dbWCMk6SYGTAMQ8/zIIRB4OesIvo78ebrsrMfqH//1+39+/795eVlu/2PoijdbrfT6biuWwe2rMrVNO1uNBrdDg1DBw5KA5fo71jirOIWUkZR9GTOG2WdNu+owLIsbaYhD2VpLh/MhvzQMzPm8zzPVl9WNAjBBWZ3M8+0rPn9HEIYRXFZlnUbJeMfYYz5vk/p457TNE3jfKoa47tRFEXQg8hHRYGfQAhZnfJIxhgLIUw78oKMUJbltSf4ZwiCEGP8UP4fm1f8Auha8ykAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;vp ng inspector&quot; title=&quot;vp ng inspector&quot; src=&quot;/static/7330522354932cb903232b24e472b9c4/804b2/vp_ng_inspector.png&quot; srcset=&quot;/static/7330522354932cb903232b24e472b9c4/c26ae/vp_ng_inspector.png 158w,
/static/7330522354932cb903232b24e472b9c4/6bdcf/vp_ng_inspector.png 315w,
/static/7330522354932cb903232b24e472b9c4/804b2/vp_ng_inspector.png 384w&quot; sizes=&quot;(max-width: 384px) 100vw, 384px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
&lt;p&gt;I can see at a glance that the scope containing the search box (#2), is separate from the scope where I am laying out my view (the unnamed scope #5).&lt;/p&gt;
&lt;p&gt;Because of these tools, I have learned that multiple instances of the same controller do not share scope. Using ng-router, I declared the controller for the view:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;  &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;when&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;/&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;templateUrl&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;views/index.html&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;controller&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;PlaybillController&apos;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In my layout, I had declared the controller once more:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;  ...
  &amp;lt;div ng-controller=&quot;PlaybillController&quot;&gt;
    &amp;lt;form class=&quot;navbar-form navbar-left&quot; role=&quot;search&quot;&gt;
      &amp;lt;div class=&quot;form-group&quot;&gt;
        &amp;lt;input type=&quot;text&quot; class=&quot;form-control&quot; placeholder=&quot;Search shows&quot; ng-model=&quot;search.title&quot;&gt;
      &amp;lt;/div&gt;
    &amp;lt;/form&gt;
  &amp;lt;/div&gt;
  ...&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The search box was already in the context of a Playbill Controller, and I had inadvertently put in another. The solution was to simply remove the second ng-controller:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;  ...
  &amp;lt;div&gt;
    &amp;lt;form class=&quot;navbar-form navbar-left&quot; role=&quot;search&quot;&gt;
      &amp;lt;div class=&quot;form-group&quot;&gt;
        &amp;lt;input type=&quot;text&quot; class=&quot;form-control&quot; placeholder=&quot;Search shows&quot; ng-model=&quot;search.title&quot;&gt;
      &amp;lt;/div&gt;
    &amp;lt;/form&gt;
  &amp;lt;/div&gt;
  ...&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I have been growing my Ruby/Rails troubleshooting toolbox for a while now, and it is good to get one started for angular as well.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[more git goodies]]></title><description><![CDATA[Becoming a git expert is essential to efficiency and confidence as a software developer. I have evolved from someone who would re-clone the…]]></description><link>http://katieleonard.ca/blog/2015/2015-03-08-more-git-goodies/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2015/2015-03-08-more-git-goodies/</guid><pubDate>Sun, 08 Mar 2015 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Becoming a git expert is essential to efficiency and confidence as a software developer. I have evolved from someone who would re-clone the repo in case of a botched merge to a savvy git handler, through:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Moving files between working directory, index, stash, and commit history&lt;/li&gt;
&lt;li&gt;Working with multiple remotes with many contributors&lt;/li&gt;
&lt;li&gt;Handling changes to forks, branches, and pull requests&lt;/li&gt;
&lt;li&gt;Accidental merges from pulling upstream, and checking out pull requests or remote branches&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; rebase -i &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;sha&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# pick a sha from your git history and start squashing&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; clean -f &lt;span class=&quot;token comment&quot;&gt;# removes untracked files from your working directory&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; stash &lt;span class=&quot;token comment&quot;&gt;# save your idea for later&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; stash pop &lt;span class=&quot;token comment&quot;&gt;# revive your last idea&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; reflog &lt;span class=&quot;token comment&quot;&gt;# oh my goodness, what did I just do?&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# Add this to your .bashrc (or .zshrc)&lt;/span&gt;
&lt;span class=&quot;token builtin class-name&quot;&gt;alias&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;wip&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;git add .; git commit -m &apos;WIP&apos;&quot;&lt;/span&gt;  &lt;span class=&quot;token comment&quot;&gt;# saves and commits the current state&lt;/span&gt;
&lt;span class=&quot;token builtin class-name&quot;&gt;alias&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;popwip&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;git reset --soft head~1; git reset head .&quot;&lt;/span&gt;  &lt;span class=&quot;token comment&quot;&gt;# pops the top commit off the stack&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# Add this to your git config&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;alias&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
  hist &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; log --pretty&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;format:&lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;&quot;%h %ad &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; %s%d &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;%an&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;&quot; --graph --date&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;short

$ &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; hist &lt;span class=&quot;token comment&quot;&gt;# opens a human readable history -- essential for verifying where you are:&lt;/span&gt;
* 2ae2be1 &lt;span class=&quot;token number&quot;&gt;2015&lt;/span&gt;-03-08 &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; WIP &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;HEAD, origin/source, &lt;span class=&quot;token builtin class-name&quot;&gt;source&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;keighty&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
* 247f86f &lt;span class=&quot;token number&quot;&gt;2015&lt;/span&gt;-02-16 &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; Change portfolio subtitle. &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;keighty&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
* e2a4fd0 &lt;span class=&quot;token number&quot;&gt;2015&lt;/span&gt;-02-16 &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; Add facebook and google+ sharing options. &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;keighty&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
* e41ca0a &lt;span class=&quot;token number&quot;&gt;2015&lt;/span&gt;-02-16 &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; Replace comments &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; draft and post tasks. &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;keighty&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;.&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; checkout -b &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;name of the &lt;span class=&quot;token builtin class-name&quot;&gt;local&lt;/span&gt; branch to create&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; upstream/&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;name of the remote branch&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; checkout - &lt;span class=&quot;token comment&quot;&gt;# checks out the last branch you were on&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; checkout -p &lt;span class=&quot;token comment&quot;&gt;# checks out changes in chunks&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I have already shared a few tools that have become so much a part of my tool box, and have developed such a muscle memory that my fingers will perform the tasks as I think them. Every time I pair with another developer I gain another shortcut! Thanks to Vince for those last two…&lt;/p&gt;</content:encoded></item><item><title><![CDATA[bird by bird]]></title><description><![CDATA[Virtue is its own reward, and so is writing. Anne Lamott’s Bird by Bird: Some Instructions on Writing and Life is full of beautiful prose…]]></description><link>http://katieleonard.ca/blog/2015/2015-02-27-bird-by-bird/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2015/2015-02-27-bird-by-bird/</guid><pubDate>Sun, 01 Mar 2015 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Virtue is its own reward, and so is writing. Anne Lamott’s &lt;a href=&quot;http://www.amazon.com/Bird-Some-Instructions-Writing-Life/dp/0385480016/ref=sr_1_1?ie=UTF8&amp;#x26;qid=1425241344&amp;#x26;sr=8-1&amp;#x26;keywords=bird+by+bird&quot;&gt;Bird by Bird: Some Instructions on Writing and Life&lt;/a&gt; is full of beautiful prose, characters, and personal anecdotes, and while her advice is tuned to the creative writer, there are three useful lessons that can be applied to all writing.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;write short assignments&lt;/li&gt;
&lt;li&gt;write only what you can see through a 1-inch picture frame&lt;/li&gt;
&lt;li&gt;write a terrible first draft&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Blogging about what I am learning and reading forces me to think about what I experience. Almost every day I learn another 1-inch picture frame of programming, and writing it down helps me understand it better. My ugly first drafts usually consist of a question, a few links to resources, and some console output — not Pulitzer Prize winning prose, but an awesome personal resource and record of growth.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;All you can give us is what life is about from your point of view. You are not going to be able to give us the plans to the submarine. Life is not a submarine. There are no plans.&lt;/p&gt;
&lt;/blockquote&gt;</content:encoded></item><item><title><![CDATA[uploading images from node and angular to s3]]></title><description><![CDATA[Amazon Web Services allow you to do everything, so it is hard to figure out how to do anything. I have a node/angular/mongo stack running on…]]></description><link>http://katieleonard.ca/blog/2015/2015-02-20-uploading-images-from-node-slash-angular-to-s3/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2015/2015-02-20-uploading-images-from-node-slash-angular-to-s3/</guid><pubDate>Tue, 24 Feb 2015 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Amazon Web Services allow you to do everything, so it is hard to figure out how to do anything. I have a node/angular/mongo stack running on Heroku, and want to use Amazon to store images. I was delighted to stumble across &lt;a href=&quot;https://devcenter.heroku.com/articles/s3-upload-node&quot;&gt;&lt;em&gt;Direct to S3 Uploads in Node.js&lt;/em&gt;&lt;/a&gt;, written by Will Webberly for the Heroku Dev Center blog.
Following his &lt;a href=&quot;https://github.com/flyingsparx/NodeDirectUploader&quot;&gt;example&lt;/a&gt;, I was able to upload images directly from the browser to S3, saving my app server a whole lot of work.&lt;/p&gt;
&lt;!--more--&gt;
&lt;p&gt;In the example, when a user selects a file for upload, the browser asks the node server for a temporary signed request. The server replies with a signed url, and the browser can send the data directly to Amazon. TADA — Almost. With a few exceptions. One of the prerequisites is that you know how to set up an S3 bucket and IAM user with the correct access controls.&lt;/p&gt;
&lt;h4&gt;Setting the S3 stage&lt;/h4&gt;
&lt;p&gt;When S3 receives a request it must verify that the requester has the proper permissions — both at the account level, as well as at the bucket level. With a seemingly infinite number of services available through Amazon, I found that I had to aggregate information from a few different sources.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Create a bucket&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;See &lt;a href=&quot;http://docs.aws.amazon.com/AmazonS3/latest/gsg/CreatingABucket.html&quot;&gt;this Amazon tutorial&lt;/a&gt; for how to create a bucket.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Create a user&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;See &lt;a href=&quot;http://docs.aws.amazon.com/IAM/latest/UserGuide/Using_SettingUpUser.html#Using_CreateUser_console&quot;&gt;this Amazon tutorial&lt;/a&gt; for creating an IAM User.&lt;/li&gt;
&lt;li&gt;Be sure to record the generated &lt;code class=&quot;language-text&quot;&gt;Access Key ID&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;Secret Access Key&lt;/code&gt;. They will act as user name and password for accessing your bucket.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Grant the IAM User access to S3&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;In the IAM User section of the AWS Management Console, select &lt;code class=&quot;language-text&quot;&gt;Attach Policy&lt;/code&gt;, and add &lt;code class=&quot;language-text&quot;&gt;AmazonS3FullAccess&lt;/code&gt; from the list
&lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/7abbe00cbe559af05e5d963db4e23749/b7877/IAM_Management_Console.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 27.21518987341772%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAFCAIAAADKYVtkAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAqklEQVQY033Kyw7BQBQA0Pn/P/AJxFZsupB0wcJC7AgSjypt59W587p3GpLakOCsD9OS34tjfTsDV6CMFIILLr7RvfYN25eQrcp83Yy2+bTI29aAAduDnrX2VYno8Yktd2ow2Qxnl/FhkVVzRCQi7NEnRNRaxRi6RImQEFlyvKmKRipnKDqM4Sfn/ela1UKL1lbCgPUsBQDrJJAAH4i6P1IHIYFH8KhtjJiexhcbbUHxEeYAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;IAM Management Console&quot; title=&quot;IAM Management Console&quot; src=&quot;/static/7abbe00cbe559af05e5d963db4e23749/f058b/IAM_Management_Console.png&quot; srcset=&quot;/static/7abbe00cbe559af05e5d963db4e23749/c26ae/IAM_Management_Console.png 158w,
/static/7abbe00cbe559af05e5d963db4e23749/6bdcf/IAM_Management_Console.png 315w,
/static/7abbe00cbe559af05e5d963db4e23749/f058b/IAM_Management_Console.png 630w,
/static/7abbe00cbe559af05e5d963db4e23749/b7877/IAM_Management_Console.png 891w&quot; sizes=&quot;(max-width: 630px) 100vw, 630px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Grant the IAM User access to the bucket&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Use &lt;a href=&quot;http://awspolicygen.s3.amazonaws.com/policygen.html&quot;&gt;this Amazon tool&lt;/a&gt; to help you generate an Access Control Policy. The key pieces you need for the policy generator are the AWS Principle (the user you created), which you enter in the format &lt;code class=&quot;language-text&quot;&gt;arn:aws:iam::&amp;lt;your_account_number&gt;:&amp;lt;IAM_user_name&gt;&lt;/code&gt;, and the Resource (the bucket you created), which you enter in the format &lt;code class=&quot;language-text&quot;&gt;arn:aws:s3:::&amp;lt;your_bucket_name&gt;/*&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;{
  &quot;Version&quot;:&quot;2012-10-17&quot;,
  &quot;Id&quot;: &quot;Policy1234567890123&quot;,
  &quot;Statement&quot;:[{
    &quot;Sid&quot;:&quot;Stmt123456789&quot;,
    &quot;Effect&quot;:&quot;Allow&quot;,
    &quot;Principal&quot;: {
            &quot;AWS&quot;: &quot;arn:aws:iam::111122223333:specialUser&quot;
    },
    &quot;Action&quot;:[
      &quot;s3:PutObject&quot;,
      &quot;s3:DeleteObject&quot;,
      &quot;s3:GetObject&quot;
    ],
    &quot;Resource&quot;:&quot;arn:aws:s3:::examplebucket/*&quot;
  }]
}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In case you get lost, here is &lt;a href=&quot;http://docs.aws.amazon.com/AmazonS3/latest/dev/how-s3-evaluates-access-control.html&quot;&gt;one more invaluable Amazon tutorial&lt;/a&gt;.&lt;/p&gt;
&lt;h4&gt;Angular client side&lt;/h4&gt;
&lt;p&gt;Using an angular app on the client side is also a slight deviation from the Webberly tutorial. Angular &lt;a href=&quot;https://github.com/angular/angular.js/issues/1375&quot;&gt;does not support&lt;/a&gt; an &lt;code class=&quot;language-text&quot;&gt;ng-change&lt;/code&gt; binding on file input elements, but there is a &lt;a href=&quot;http://stackoverflow.com/a/17923521&quot;&gt;workaround&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;&amp;lt;input type=&quot;file&quot; class=&quot;form-control btn&quot; id=&quot;image&quot; onchange=&quot;angular.element(this).scope().s3Upload(this)&quot;&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Additionally, instead of adding the upload function as plain javascript in your html template, add the &lt;code class=&quot;language-text&quot;&gt;s3Upload&lt;/code&gt; function onto the &lt;code class=&quot;language-text&quot;&gt;$scope&lt;/code&gt; in your controller.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;$scope&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function-variable function&quot;&gt;s3Upload&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; status_elem &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getElementById&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;status&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; url_elem &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getElementById&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;image_url&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; preview_elem &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getElementById&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;preview&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; s3upload &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;S3Upload&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token literal-property property&quot;&gt;s3_object_name&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;showTitleUrl&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;  &lt;span class=&quot;token comment&quot;&gt;// upload object with a custom name&lt;/span&gt;
      &lt;span class=&quot;token literal-property property&quot;&gt;file_dom_selector&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;image&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token literal-property property&quot;&gt;s3_sign_put_url&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;/sign_s3&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token function-variable function&quot;&gt;onProgress&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;percent&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; message&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
          status_elem&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;innerHTML &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Upload progress: &apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; percent &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;% &apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; message&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token function-variable function&quot;&gt;onFinishS3Put&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;public_url&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
          status_elem&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;innerHTML &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Upload completed. Uploaded to: &apos;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; public_url&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
          url_elem&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;value &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; public_url&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
          preview_elem&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;innerHTML &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;&amp;lt;img src=&quot;&apos;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; public_url &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;&quot; style=&quot;width:300px;&quot; /&gt;&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token function-variable function&quot;&gt;onError&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;status&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
          status_elem&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;innerHTML &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Upload error: &apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; status&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Note the diff on line 6 — taking a peek into the &lt;a href=&quot;https://github.com/flyingsparx/NodeDirectUploader/blob/master/public/javascripts/s3upload.js#L23-L29&quot;&gt;S3Upload source&lt;/a&gt;, you can set a custom file name by passing a &lt;code class=&quot;language-text&quot;&gt;s3_object_name&lt;/code&gt; option. Otherwise, every object will be named &lt;code class=&quot;language-text&quot;&gt;default_name&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;$scope&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function-variable function&quot;&gt;s3_upload&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; s3upload &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;S3Upload&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;s3_object_name&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;showTitleUrl&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;  &lt;span class=&quot;token comment&quot;&gt;// upload object with a custom name&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;file_dom_selector&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;image&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;s3_sign_put_url&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;/sign_s3&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;showTitleUrl&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; title &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; $scope&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;show&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;title&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos; &apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;_&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; dateId &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Date&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;now&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; dateId &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; title&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h4&gt;Add &lt;code class=&quot;language-text&quot;&gt;image&lt;/code&gt; to your schema&lt;/h4&gt;
&lt;p&gt;The last stumbling block I encountered was saving the image url into mongo. The image would upload and appear just fine, but wouldn’t persist the url as a property of the object. I had forgotten to add the image to my mongo Schema — the schema acts a bit like a whitelist for saving attributes through mongoose into mongo. Adding the &lt;a href=&quot;https://github.com/keighty/virtualplaybill2/blob/ad04bcde8ce00c5ce349f43d2e0cc50549c59df7/models/posts_model.js#L11&quot;&gt;imageUrl to the schema&lt;/a&gt; solved all my woes.&lt;/p&gt;
&lt;p&gt;If you are trying to accomplish something similar, Heroku has articles on &lt;a href=&quot;https://devcenter.heroku.com/articles/s3&quot;&gt;uploading directly to S3&lt;/a&gt; using many different stacks.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[everybody writes (and why you should blog)]]></title><description><![CDATA[In Everybody Writes, Ann Handley teaches content marketers how to generate “ridiculously good” content. Anyone who has recently enjoyed the…]]></description><link>http://katieleonard.ca/blog/2015/2015-02-14-everybody-writes/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2015/2015-02-14-everybody-writes/</guid><pubDate>Mon, 16 Feb 2015 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;In &lt;em&gt;Everybody Writes&lt;/em&gt;&lt;sup id=&quot;fnref-1&quot;&gt;&lt;a href=&quot;#fn-1&quot; class=&quot;footnote-ref&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;, Ann Handley teaches content marketers how to generate “ridiculously good” content. Anyone who has recently enjoyed the pain of the job hunt will notice that much of the advice can be adapted to self-marketing. In my recent code school experience, developing an online presence was as important as learning web development, and since it is hard to market yourself as a web developer without developing anything for the web, a blog is a great place to start. You have picked a career where your ability to learn is one of your most marketable skills, as well as your ability to communicate — both of which you can showcase in your blog. You don’t have to worry about having something original to say: treat it as an opportunity to organize your thoughts and to teach a beginner what you know. Handley gives great advice for people learning to blog and how to generally optimize your online presence — both are great ways to market yourself as a fresh code-school alum.&lt;/p&gt;
&lt;!--more--&gt;
&lt;h3&gt;Show up&lt;/h3&gt;
&lt;p&gt;Write early, write often. If something is new to you, it will likely be new to someone else as well. The more writing practice you get, the easier it becomes — “writing is a habit, not an art”, and you can’t help but improve in an art that you practice every day. Handley recommends starting with the ugly first draft&lt;sup id=&quot;fnref-2&quot;&gt;&lt;a href=&quot;#fn-2&quot; class=&quot;footnote-ref&quot;&gt;2&lt;/a&gt;&lt;/sup&gt; — make it ugly, don’t delete anything, don’t rephrase or reread. Just get it out of you and on to your screen, then walk away for a day. Maybe two. If you are really stuck on how to begin, you could start with “Dear diary”&lt;sup id=&quot;fnref-3&quot;&gt;&lt;a href=&quot;#fn-3&quot; class=&quot;footnote-ref&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;. This helps you get in the mood to write, and keeps your tone conversational. Also, if you are writing to a non-technical person, it will keep your writing clear, and inspire you to give enough back story so that they aren’t lost.&lt;/p&gt;
&lt;h3&gt;Write a tight post&lt;/h3&gt;
&lt;h4&gt;Decide on a goal&lt;/h4&gt;
&lt;p&gt;Is it to teach? To share? To critique? The goal for technical blogs is not usually to obtain a following — it is to share a bit of experience that will turn up when another frustrated developer puts keywords into a search engine. An online presence is important, but it should not be a blow by blow of how hard it is to learn to code. A handy formula for creating quality content is:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Utility * Inspiration * Empathy = Quality Content&lt;sup id=&quot;fnref-4&quot;&gt;&lt;a href=&quot;#fn-4&quot; class=&quot;footnote-ref&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Make it useful, make it reader centric (even if that reader is you six months from now), and make it thoughtful.&lt;/p&gt;
&lt;h4&gt;Forget the 5 paragraph essay format from high school&lt;/h4&gt;
&lt;p&gt;I rarely read a long blog post from beginning to end, and the sweet spot for length is around 1500 words&lt;sup id=&quot;fnref-5&quot;&gt;&lt;a href=&quot;#fn-5&quot; class=&quot;footnote-ref&quot;&gt;5&lt;/a&gt;&lt;/sup&gt;. Make it easy for the reader to get the gist of your post by providing sub-headings, bold text, and code samples — these are strong visual elements that can help your reader anchor what they are learning.&lt;/p&gt;
&lt;h4&gt;Rewrite&lt;/h4&gt;
&lt;p&gt;Once you have written the ugly first draft with your goal in mind, rewrite it with the reader in mind — will they understand the context of what you are trying to get across? Assume the reader knows nothing, but isn’t stupid. Find data and examples that illustrate what you are trying to share (and make sure that you give credit where credit is due&lt;sup id=&quot;fnref-6&quot;&gt;&lt;a href=&quot;#fn-6&quot; class=&quot;footnote-ref&quot;&gt;6&lt;/a&gt;&lt;/sup&gt;).&lt;/p&gt;
&lt;h4&gt;Work on your grammar&lt;/h4&gt;
&lt;p&gt;After reframing, examine your sentence structure. Are you using a passive voice? Microsoft Word grammar check hates the passive voice, but I never knew what that meant. Try &lt;a href=&quot;https://www.grammarly.com/&quot;&gt;grammarly&lt;/a&gt; if you need help, and even if you think you don’t. Editing your own work is hard, because your brain will fill in all the things you meant to say but didn’t. Also, put the important words at the start of the sentence, just in case the reader dozes off half-way through.&lt;/p&gt;
&lt;h3&gt;About Me pages&lt;/h3&gt;
&lt;p&gt;Be intentional about the words that describe you in your About Me page&lt;sup id=&quot;fnref-7&quot;&gt;&lt;a href=&quot;#fn-7&quot; class=&quot;footnote-ref&quot;&gt;7&lt;/a&gt;&lt;/sup&gt;. Describe your accomplishments with examples, and if possible, try to mirror the language used by the companies you want to work for. Check out the keywords they use, and make sure to encorporate them in your headlines and personal summary.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;About us pages aren’t really about the company; instead they focus on relaying who they are &lt;em&gt;in relation to the visitor&lt;/em&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;If your reader is an employer, let them know you are for hire — your posts should always be in the context of what you can do for the reader.&lt;/p&gt;
&lt;p&gt;Showing up can be the hardest thing — finding something original to say, or fearing a public mistake is what keeps many people from writing, but blogging shows you are interested in, well, something. Being interesting means being interested in things, and wanting to share the things you find interesting is a natural follow through. Given the right mentorship, your technical abilities will grow, but getting in the door is step one. So, if you are looking to update your web presence, or create a web presence, this book is for you.&lt;/p&gt;
&lt;div class=&quot;footnotes&quot;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&quot;fn-1&quot;&gt;
&lt;p&gt;Handley, A. (2014). &lt;a href=&quot;http://www.amazon.com/Everybody-Writes-Go--Creating-Ridiculously-ebook/dp/B00LMB5P0G/ref=sr_1_1?ie=UTF8&amp;#x26;qid=1424115248&amp;#x26;sr=8-1&amp;#x26;keywords=everybody+writes&quot;&gt;&lt;em&gt;Everybody Writes : Your Go-To Guide to Creating Ridiculously Good Content&lt;/em&gt;&lt;/a&gt;. Wiley &amp;#x26; Sons Canada, Limited, John.&lt;/p&gt;
&lt;a href=&quot;#fnref-1&quot; class=&quot;footnote-backref&quot;&gt;↩&lt;/a&gt;
&lt;/li&gt;
&lt;li id=&quot;fn-2&quot;&gt;
&lt;p&gt;Tip 9: “Embrace the Ugly First Draft”, p. 41.&lt;/p&gt;
&lt;a href=&quot;#fnref-2&quot; class=&quot;footnote-backref&quot;&gt;↩&lt;/a&gt;
&lt;/li&gt;
&lt;li id=&quot;fn-3&quot;&gt;
&lt;p&gt;Tip 14: “Start with &lt;em&gt;Dear Mom…&lt;/em&gt;”, p. 54.&lt;/p&gt;
&lt;a href=&quot;#fnref-3&quot; class=&quot;footnote-backref&quot;&gt;↩&lt;/a&gt;
&lt;/li&gt;
&lt;li id=&quot;fn-4&quot;&gt;
&lt;p&gt;“Introduction”, p. 7.&lt;/p&gt;
&lt;a href=&quot;#fnref-4&quot; class=&quot;footnote-backref&quot;&gt;↩&lt;/a&gt;
&lt;/li&gt;
&lt;li id=&quot;fn-5&quot;&gt;
&lt;p&gt;Tip 60: “The Ideal Length for Blog Posts, Podcast, Facebook Posts, Tweets, and Other Marketing Content”, p. 184.&lt;/p&gt;
&lt;a href=&quot;#fnref-5&quot; class=&quot;footnote-backref&quot;&gt;↩&lt;/a&gt;
&lt;/li&gt;
&lt;li id=&quot;fn-6&quot;&gt;
&lt;p&gt;Tip 57: “Seek Permission, Not Forgiveness”, p. 170.&lt;/p&gt;
&lt;a href=&quot;#fnref-6&quot; class=&quot;footnote-backref&quot;&gt;↩&lt;/a&gt;
&lt;/li&gt;
&lt;li id=&quot;fn-7&quot;&gt;
&lt;p&gt;Tip 71: “Writing the About Us Page”, p 244.&lt;/p&gt;
&lt;a href=&quot;#fnref-7&quot; class=&quot;footnote-backref&quot;&gt;↩&lt;/a&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</content:encoded></item><item><title><![CDATA[clean code]]></title><description><![CDATA[The book club I belong to has a two-fold mission: the first is to inspire through peer pressure to read (and finish) technical books, and…]]></description><link>http://katieleonard.ca/blog/2015/2015-02-07-clean-code/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2015/2015-02-07-clean-code/</guid><pubDate>Sat, 07 Feb 2015 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;The book club I belong to has a two-fold mission: the first is to inspire through peer pressure to read (and finish) technical books, and the second is to improve our ability to write quality, maintainable code. We started with &lt;a href=&quot;http://www.amazon.com/Practical-Object-Oriented-Design-Ruby-Addison-Wesley/dp/0321721330/ref=sr_1_1?ie=UTF8&amp;#x26;qid=1423423708&amp;#x26;sr=8-1&amp;#x26;keywords=practical+object-oriented+design+in+ruby&quot;&gt;&lt;em&gt;Practical Object Oriented Design in Ruby&lt;/em&gt;&lt;/a&gt; (Sandi Metz), and are now on to &lt;a href=&quot;http://www.amazon.com/s/ref=nb_sb_ss_i_0_11?url=search-alias%3Daps&amp;#x26;field-keywords=refactoring&amp;#x26;sprefix=refactoring%2Caps%2C217&quot;&gt;&lt;em&gt;Refactoring&lt;/em&gt;&lt;/a&gt; (Martin Fowler and Kent Beck). Along the way, I found a copy of &lt;a href=&quot;http://www.amazon.com/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882/ref=sr_1_1?ie=UTF8&amp;#x26;qid=1423423781&amp;#x26;sr=8-1&amp;#x26;keywords=clean+code&quot;&gt;&lt;em&gt;Clean Code&lt;/em&gt;&lt;/a&gt; by Robert C. Martin in our work library, and dove right in. These three books tout many of the the same principles but focus on different aspects of writing quality code: POODR teaches how to identify abstractions, and to design decoupled objects; Refactoring is a deep dive into the techniques and heuristics for eliminating common code smells; and Clean Code is the intersection between them. It is a style guide, a call to action, and a cautionary tale from the voices of experience. I had several aha moments while reading Clean Code, and here are a few&lt;!--more--&gt;:&lt;/p&gt;
&lt;h3&gt;Error handling&lt;/h3&gt;
&lt;p&gt;When I started to anticipate &lt;code class=&quot;language-text&quot;&gt;undefined method &apos;length&apos; for nil:NilClass&lt;/code&gt; errors, I knew I was growing as a developer.
Having traced the source of &lt;code class=&quot;language-text&quot;&gt;undefined is not a function&lt;/code&gt; enough times, I came to realize that I was not sufficiently controlling the messages passing between objects.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ruby&quot;&gt;&lt;pre class=&quot;language-ruby&quot;&gt;&lt;code class=&quot;language-ruby&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token method-definition&quot;&gt;&lt;span class=&quot;token function&quot;&gt;find_a_user&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token variable&quot;&gt;@user&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; User&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;where&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token symbol&quot;&gt;last_name&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Bacon&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;first
&lt;span class=&quot;token keyword&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token symbol&quot;&gt;:find_a_user&lt;/span&gt;

find_a_user
&lt;span class=&quot;token variable&quot;&gt;@user&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;last_name

&lt;span class=&quot;token symbol&quot;&gt;NoMethodError&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; undefined method `last_name&apos; &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;token symbol&quot;&gt;:NilClass&lt;/span&gt;
from &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;pry&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token symbol&quot;&gt;:in&lt;/span&gt; `__pry__&apos;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This first pass seemed totally reasonable to me — find a particular user, and return it. Of course, what if the user doesn’t exist? What if the query timed out? The code on line 7 is reasonable (wherever it may live), but if &lt;code class=&quot;language-text&quot;&gt;@user&lt;/code&gt; is set to nil my app will blow up. The worst part is, it will blow up at quite a distance from where the actual problem is. A naive solution would be to check if &lt;code class=&quot;language-text&quot;&gt;@user&lt;/code&gt; is nil before calling &lt;code class=&quot;language-text&quot;&gt;#last_name&lt;/code&gt; on it (&lt;code class=&quot;language-text&quot;&gt;@user.last_name if @user&lt;/code&gt;), but this leads to unreadable, untrustworthy code. {“The problem isn’t that the code is missing a null check, but that it has too many.“} I have a poor contract with &lt;code class=&quot;language-text&quot;&gt;User&lt;/code&gt; if I have to check its validity every time I ask it a question. Martin suggests a more sustainable solution — &lt;em&gt;never return &lt;code class=&quot;language-text&quot;&gt;nil&lt;/code&gt;&lt;/em&gt;. If you never return &lt;code class=&quot;language-text&quot;&gt;nil&lt;/code&gt;, you don’t have to catch &lt;code class=&quot;language-text&quot;&gt;nil&lt;/code&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;If you are calling a [nil]-returning method from a third-party API, consider wrapping that method with a method that either throws an exception or returns a special case object.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ruby&quot;&gt;&lt;pre class=&quot;language-ruby&quot;&gt;&lt;code class=&quot;language-ruby&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token method-definition&quot;&gt;&lt;span class=&quot;token function&quot;&gt;find_a_user&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;@user&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; User&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;where&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token symbol&quot;&gt;last_name&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Bacon&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;first
    &lt;span class=&quot;token variable&quot;&gt;@user&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;raise&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;StandardError&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Could not find Mr. Bacon.&quot;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;end&lt;/span&gt;

find_a_user
&lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; StandardError&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Could &lt;span class=&quot;token keyword&quot;&gt;not&lt;/span&gt; find Mr&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt; Bacon&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now the error occurs where it belongs — with the retrieval of the user. Throwing an error when something goes wrong is the least you can do for the consumers of your method. You could also solidify your contract by guaranteeing that you return something they expect.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ruby&quot;&gt;&lt;pre class=&quot;language-ruby&quot;&gt;&lt;code class=&quot;language-ruby&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token method-definition&quot;&gt;&lt;span class=&quot;token function&quot;&gt;interesting_things&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token variable&quot;&gt;@interesting_things&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;end&lt;/span&gt;

interesting_things&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length
&lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I have guaranteed that &lt;code class=&quot;language-text&quot;&gt;#interesting_things&lt;/code&gt; will always return either the collection I expect or a reasonable facscimile. It is a simple enough solution, but I definitely felt that message sink into place. Methods are objects and objects have API’s: messages in and messages out. Make those messages deliberate, because if “returning null from methods is bad, passing null into methods is worse.”&lt;/p&gt;
&lt;h3&gt;Protect Your Boundaries&lt;/h3&gt;
&lt;p&gt;Controlling the messages going in to and coming out of your objects is one place you need to protect your boundaries, but what about objects from 3rd party libraries or frameworks? There are consequences of relying too heavily on a library API, and in Chapter 9: Boundaries, James Grenning shares a few of them. One system he was working with collected information by passing around a Map collection, which is a standard library data structure in Java. In the next version of Java, new capabilities were added, and in order to use the new feature they had to find everywhere the object was used and make the change.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;We’ve seen systems that are inhibited from using [the new feature] because of the sheer magnitude of changes needed to make up for the liberal use of Maps.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I recently had a similar experience when upgrading an application from Rails 3.0 to Rails 3.2, where there were drastic changes to how models record errors. Errors inherited from OrderedHash in Rails 3.0 and from ActiveModel in Rails 3.2 — very different object types. Every test that looked for errors called &lt;code class=&quot;language-text&quot;&gt;errors.on&lt;/code&gt; — now a deprecated method. Every place that looped over the collection with &lt;code class=&quot;language-text&quot;&gt;errors.each&lt;/code&gt; had to be changed to &lt;code class=&quot;language-text&quot;&gt;errors.messages.each&lt;/code&gt;, or the logic modified altogether. It is good practice to be distrustful of APIs that are likely to change, and while I don’t believe that the Errors object ever seemed unstable, it has certainly made me extra cautious of calling 3rd party framework methods directly.&lt;/p&gt;
&lt;h3&gt;Clean Code is not a “nice-to-have”&lt;/h3&gt;
&lt;p&gt;Technical debt is not a decision to be okay with untested, brittle code that is impossible to build on — it is a decision to pursue a design that may not be scalable, but it can still be clean. It is tempting to declare “Mission Accomplished” when you have reached the point of working code, but the job is really only half done:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;It is not enough for code to work. Code that works is often badly broken. Programers who satisfy themselves with merely working code are behaving unprofessionally. They may fear that they don’t have time to improve the structure and design of their code, but I disagree. Nothing has a more profound and long term degrading effect upon a development project than bad code. Bad schedules can be redone, bad requirements can be redefined. Bad team dynamics can be repaired. But bad code rots and ferments, becoming an inexorable weight that drags the team down.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;A story cannot be declared finished until the code is ammenable to change. In order to change code, it must be comprehensible and thoroughly tested. Compromising code quality to meet the demands of a schedule will only slow things down in the long run.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Clean Code&lt;/em&gt; is a must read for all professional software developers. Leaving clean code is not just a kindness to the next developer (which is likely to be you), but is essential for growing a healthy codebase. Of course, “to write clean code, you must first write dirty code and then clean it,” and I look forward to learning new techniques as we tackle &lt;em&gt;Refactoring&lt;/em&gt;.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[debugging techniques]]></title><description><![CDATA[I am working on upgrading an application from Rails 3.0 to Rails 3.2. While the numbers tell you it is a minor version change, there are…]]></description><link>http://katieleonard.ca/blog/2015/2015-02-02-debugging-techniques/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2015/2015-02-02-debugging-techniques/</guid><pubDate>Mon, 02 Feb 2015 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I am working on upgrading an application from Rails 3.0 to Rails 3.2. While the numbers tell you it is a minor version change, there are definitely some major challenges. Digging through Rails and gem internals has forced me to add new strategies to my debugging toolbox, and here are a few of the essentials…&lt;!--more--&gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://github.com/burke/zeus&quot;&gt;Zeus&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Zeus is a gem that preloads your Rails app and keeps it loaded, making test driven development fast. Just type &lt;code class=&quot;language-text&quot;&gt;zeus start&lt;/code&gt; in one console window, and any of the listed commands in another console window.&lt;/p&gt;
&lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 460px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/3d6805b304b537183fa34f272d2fd016/08a84/zeus_start.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 81.64556962025317%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAQCAIAAACZeshMAAAACXBIWXMAAAsTAAALEwEAmpwYAAACFUlEQVQoz4WT23LaMBCG/f6v1Ys009AhGAz4IMsSkoUN+CBZRyx1CElz0dDs/KPZvVj9365GUTVt44HueLPq8OLQxmO3VjXrcFIuD+f8NX8Rcgoh+ODDPxGhKd0Nv3ZiNZL1GGdDkVC0AG2b1SwlDLDGno1m+n6axhpLbpkmxjTRuv+56p/PtrXtyVCsS3hl7bG5wsoiZAl1hmlVKU21wkpTozW61RIYc4y4JhddV1NKTdW6E7YQKeBm+8blw1e0n9ghBOO6yTQlX+djHHdPcfdMFaKyqiUGfAtFqp16u+c+uP+ryIcwX0UIQdtzp2sgkozHTGHnnfPWBz/72T/wj7wP11lfHacSoCnfD0sosu3wsrj8GF3/vmf/oc/Mv2N/hJmD6fxx8mNr6cm0/xv37owRxgjDEtb0CCuYpTkoSsEHq5HWRMrCyFZjrBCU6V4ODdFlJfZ3qGgFF3G5XORP+8OG0RohhBEZ+rPW2NpG6dLIo6mJqYlGlezbxlIiAXfDrRmqLXOotjCXGzGPzMLaVmIeRzd+j13wDZkAmrKkfyESAp5kY3xUB6aQ8x+v/WhhgK+xLKppn/GYqqqa9qXYnXTdaua8+8a5FDsk0oyvMr6upozIIh1fiQSl2F1MG0KYw/ywOefr298Yl9vhd8GTgwQX08ir4K7/3hnwDZYFENs3JWjK5XW62JYpbGbFFGYad/b8ZfMf3zqLz+6PDlgAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;zeus start&quot; title=&quot;zeus start&quot; src=&quot;/static/3d6805b304b537183fa34f272d2fd016/08a84/zeus_start.png&quot; srcset=&quot;/static/3d6805b304b537183fa34f272d2fd016/c26ae/zeus_start.png 158w,
/static/3d6805b304b537183fa34f272d2fd016/6bdcf/zeus_start.png 315w,
/static/3d6805b304b537183fa34f272d2fd016/08a84/zeus_start.png 460w&quot; sizes=&quot;(max-width: 460px) 100vw, 460px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ zeus &lt;span class=&quot;token builtin class-name&quot;&gt;test&lt;/span&gt; test/models/user_test.rb
Run options: --seed &lt;span class=&quot;token number&quot;&gt;32298&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# Running:&lt;/span&gt;

&lt;span class=&quot;token builtin class-name&quot;&gt;.&lt;/span&gt;

Finished &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;.045991s, &lt;span class=&quot;token number&quot;&gt;21.7434&lt;/span&gt; runs/s, &lt;span class=&quot;token number&quot;&gt;21.7434&lt;/span&gt; assertions/s.

&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; runs, &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; assertions, &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; failures, &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; errors, &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; skips&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Run a specific test in a file by passing a regex argument:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ zeus &lt;span class=&quot;token builtin class-name&quot;&gt;test&lt;/span&gt; test/models/user_test.rb -n &lt;span class=&quot;token string&quot;&gt;&quot;/test_user_description_has_full_name/&quot;&lt;/span&gt;
Run options: -n /test_user_description_has_full_name/ --seed &lt;span class=&quot;token number&quot;&gt;17927&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# Running:&lt;/span&gt;

&lt;span class=&quot;token builtin class-name&quot;&gt;.&lt;/span&gt;

Finished &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;.044550s, &lt;span class=&quot;token number&quot;&gt;22.4467&lt;/span&gt; runs/s, &lt;span class=&quot;token number&quot;&gt;22.4467&lt;/span&gt; assertions/s.

&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; runs, &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; assertions, &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; failures, &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; errors, &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; skips&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;&lt;a href=&quot;https://github.com/pry/pry&quot;&gt;Pry&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The Pry gem allows you to set break points and open an interactive debug session at any place in your code using &lt;code class=&quot;language-text&quot;&gt;binding.pry&lt;/code&gt;. A great way to debug a failing test is to place a pry at the top of the test and check your setup:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ruby&quot;&gt;&lt;pre class=&quot;language-ruby&quot;&gt;&lt;code class=&quot;language-ruby&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&apos;test_helper&apos;&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UserTest&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; ActiveSupport&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;TestCase
  &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token method-definition&quot;&gt;&lt;span class=&quot;token function&quot;&gt;test_user_description_has_full_name&lt;/span&gt;&lt;/span&gt;
    user &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; User&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;create&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token symbol&quot;&gt;first_name&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;hello&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token symbol&quot;&gt;last_name&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;kitty&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token symbol&quot;&gt;email&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;kitty@example.com&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

    binding&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;pry

    assert_equal &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;hello kitty&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;full_name
  &lt;span class=&quot;token keyword&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ zeus &lt;span class=&quot;token builtin class-name&quot;&gt;test&lt;/span&gt; test/models/user_test.rb -n &lt;span class=&quot;token string&quot;&gt;&quot;/test_user_description_has_full_name/&quot;&lt;/span&gt;

Run options: -n /test_user_description_has_full_name/ --seed &lt;span class=&quot;token number&quot;&gt;21519&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# Running:&lt;/span&gt;

From: /Users/keighty/api_playground/test/models/user_test.rb @ line &lt;span class=&quot;token number&quot;&gt;7&lt;/span&gt; UserTest&lt;span class=&quot;token comment&quot;&gt;#test_user_description_has_full_name:&lt;/span&gt;

     &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;: def test_user_description_has_full_name
     &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;:   user &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; User.create&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;first_name: &lt;span class=&quot;token string&quot;&gt;&quot;hello&quot;&lt;/span&gt;, last_name: &lt;span class=&quot;token string&quot;&gt;&quot;kitty&quot;&lt;/span&gt;, email: &lt;span class=&quot;token string&quot;&gt;&quot;kitty@example.com&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
     &lt;span class=&quot;token number&quot;&gt;6&lt;/span&gt;:
 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;  &lt;span class=&quot;token number&quot;&gt;7&lt;/span&gt;:   binding.pry
     &lt;span class=&quot;token number&quot;&gt;8&lt;/span&gt;:
     &lt;span class=&quot;token number&quot;&gt;9&lt;/span&gt;:   assert_equal &lt;span class=&quot;token string&quot;&gt;&quot;hello kitty&quot;&lt;/span&gt;, user.full_name
    &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;: end

&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; pry&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token comment&quot;&gt;#&amp;lt;UserTest&gt;)&gt; user&lt;/span&gt;

&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;#&amp;lt;User:0x007fa054180618&lt;/span&gt;
 id: &lt;span class=&quot;token number&quot;&gt;980190963&lt;/span&gt;,
 first_name: &lt;span class=&quot;token string&quot;&gt;&quot;hello&quot;&lt;/span&gt;,
 last_name: &lt;span class=&quot;token string&quot;&gt;&quot;kitty&quot;&lt;/span&gt;,
 email: &lt;span class=&quot;token string&quot;&gt;&quot;kitty@example.com&quot;&lt;/span&gt;,
 created_at: Sat, 07 Feb &lt;span class=&quot;token number&quot;&gt;2015&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;16&lt;/span&gt;:52:21 UTC +00:00,
 updated_at: Sat, 07 Feb &lt;span class=&quot;token number&quot;&gt;2015&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;16&lt;/span&gt;:52:21 UTC +00:0&lt;span class=&quot;token operator&quot;&gt;&lt;span class=&quot;token file-descriptor important&quot;&gt;0&lt;/span&gt;&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Your pry is a debug console with more than a few extra features. Here are my favourites:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;ls object&lt;/code&gt; to see all the methods available on the object:&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; pry&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token comment&quot;&gt;#&amp;lt;UserTest&gt;)&gt; ls user&lt;/span&gt;

ActiveRecord::Core&lt;span class=&quot;token comment&quot;&gt;#methods:&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;&amp;lt;=&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;                 eql?                          &lt;span class=&quot;token builtin class-name&quot;&gt;hash&lt;/span&gt;          readonly&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt;                  freeze                        init_with     readonly?
  connection_handler  frozen?                       inspect       set_transaction_state
  encode_with         has_transactional_callbacks?  pretty_print  slice
ActiveRecord::Persistence&lt;span class=&quot;token comment&quot;&gt;#methods:&lt;/span&gt;
  becomes     delete      increment&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;   toggle&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;           update_attributes
  becomes&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;    destroy&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;    new_record?  update            update_attributes&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;
  decrement   destroyed?  persisted?   update&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;           update_column
  decrement&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;  increment   toggle       update_attribute  update_columns
ActiveRecord::Scoping&lt;span class=&quot;token comment&quot;&gt;#methods:&lt;/span&gt;
  initialize_internals_callback  populate_with_current_scope_attributes
&lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;.&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;whereami 10&lt;/code&gt; to show 10 lines above and below your breakpoint:&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; pry&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token comment&quot;&gt;#&amp;lt;UserTest&gt;)&gt; whereami 10&lt;/span&gt;

From: /Users/keighty/api_playground/test/models/user_test.rb @ line &lt;span class=&quot;token number&quot;&gt;7&lt;/span&gt; UserTest&lt;span class=&quot;token comment&quot;&gt;#test_user_description_has_full_name:&lt;/span&gt;

     &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;: require &lt;span class=&quot;token string&quot;&gt;&apos;test_helper&apos;&lt;/span&gt;
     &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;:
     &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;: class UserTest &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; ActiveSupport::TestCase
     &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;:   def test_user_description_has_full_name
     &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;:     user &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; User.create&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;first_name: &lt;span class=&quot;token string&quot;&gt;&quot;hello&quot;&lt;/span&gt;, last_name: &lt;span class=&quot;token string&quot;&gt;&quot;kitty&quot;&lt;/span&gt;, email: &lt;span class=&quot;token string&quot;&gt;&quot;kitty@example.com&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
     &lt;span class=&quot;token number&quot;&gt;6&lt;/span&gt;:
 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;  &lt;span class=&quot;token number&quot;&gt;7&lt;/span&gt;:     binding.pry
     &lt;span class=&quot;token number&quot;&gt;8&lt;/span&gt;:
     &lt;span class=&quot;token number&quot;&gt;9&lt;/span&gt;:     assert_equal &lt;span class=&quot;token string&quot;&gt;&quot;hello kitty&quot;&lt;/span&gt;, user.full_name
    &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;:   end
    &lt;span class=&quot;token number&quot;&gt;11&lt;/span&gt;:
    &lt;span class=&quot;token number&quot;&gt;12&lt;/span&gt;: end&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;cd object.method&lt;/code&gt; to navigate the object stack as if it were a folder structure (and &lt;code class=&quot;language-text&quot;&gt;ls&lt;/code&gt; to view properites):&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; pry&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token comment&quot;&gt;#&amp;lt;UserTest&gt;)&gt; cd user.full_name&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; pry&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;hello kitty&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;:&lt;span class=&quot;token operator&quot;&gt;&lt;span class=&quot;token file-descriptor important&quot;&gt;1&lt;/span&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;ls&lt;/span&gt;

Comparable&lt;span class=&quot;token comment&quot;&gt;#methods: &amp;lt;  &amp;lt;=  &gt;  &gt;=  between?&lt;/span&gt;
JSON::Ext::Generator::GeneratorMethods::String&lt;span class=&quot;token comment&quot;&gt;#methods:&lt;/span&gt;
  to_json_raw  to_json_raw_object  to_json_without_active_support_encoder
String&lt;span class=&quot;token comment&quot;&gt;#methods:&lt;/span&gt;
  %                  downcase        lstrip&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;           strip_heredoc
  *                  downcase&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;       match             sub
  +                  dump            mb_chars          sub&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;                 each_byte       next              succ
  &lt;span class=&quot;token operator&quot;&gt;&amp;lt;=&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;                each_char       next&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;             succ&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt;                 each_codepoint  not_ascii_only?   &lt;span class=&quot;token function&quot;&gt;sum&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;                each_line       oct               swapcase
  &lt;span class=&quot;token operator&quot;&gt;=~&lt;/span&gt;                 empty?          ord               swapcase&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;These are the features I use most often, but checkout the &lt;a href=&quot;http://pryrepl.org/&quot;&gt;documentation&lt;/a&gt; for more.&lt;/p&gt;
&lt;h3&gt;Method Method Method&lt;/h3&gt;
&lt;p&gt;Method name collisions can happen in a sprawling legacy codebase, so determining the source is important for debugging. The Ruby language has anticipated this difficulty, and since methods are objects themselves, they created the &lt;a href=&quot;http://www.ruby-doc.org/core-2.2.0/Method.html&quot;&gt;Method&lt;/a&gt; module to access the method object. You can source, extract, unbind, and otherwise manipulate methods in a lot of ways:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;[1] pry(#&amp;lt;UserTest&gt;)&gt; method = user.method(:full_name)
=&gt; #&amp;lt;Method: User#full_name&gt;

[2] pry(#&amp;lt;UserTest&gt;)&gt; method.owner
=&gt; User(id: integer, first_name: string, last_name: string, email: string, created_at: datetime, updated_at: datetime)

[3] pry(#&amp;lt;UserTest&gt;)&gt; method.source_location
=&gt; [&quot;/Users/keighty/api_playground/app/models/user.rb&quot;, 2]&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;Logger&lt;/h3&gt;
&lt;p&gt;Soemtimes the Rails bug you are hunting turns up in the SQL behind your query. When you are in a pry console, the SQL is not displayed by default, but you can turn on query logging by creating an &lt;code class=&quot;language-text&quot;&gt;ActiveRecord::Base.logger&lt;/code&gt; object:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;# before the logger
[1] pry(#&amp;lt;UserTest&gt;)&gt; User.find(980190963)

=&gt; #&amp;lt;User:0x007fa0556f4fd0
 id: 980190963,
 first_name: &quot;hello&quot;,
 last_name: &quot;kitty&quot;,
 email: &quot;kitty@example.com&quot;,
 created_at: Sat, 07 Feb 2015 16:52:21 UTC +00:00,
 updated_at: Sat, 07 Feb 2015 16:52:21 UTC +00:00&gt;

[2] pry(#&amp;lt;UserTest&gt;)&gt; ActiveRecord::Base.logger = Logger.new STDOUT;

[3] pry(#&amp;lt;UserTest&gt;)&gt; User.find(980190963)

D, [2015-02-07T09:28:34.892017 #10468] DEBUG -- :
User Load (0.1ms)  SELECT  &quot;users&quot;.* FROM &quot;users&quot; WHERE &quot;users&quot;.&quot;id&quot; = ? LIMIT 1  [[&quot;id&quot;, 980190963]]

=&gt; #&amp;lt;User:0x007fa05c788c10
 id: 980190963,
 first_name: &quot;hello&quot;,
 last_name: &quot;kitty&quot;,
 email: &quot;kitty@example.com&quot;,
 created_at: Sat, 07 Feb 2015 16:52:21 UTC +00:00,
 updated_at: Sat, 07 Feb 2015 16:52:21 UTC +00:00&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;If you find that you are always creating a logger, add these lines to a &lt;code class=&quot;language-text&quot;&gt;.pryrc&lt;/code&gt; file in your home directory:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; defined?&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Rails&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; Rails.env
  require &lt;span class=&quot;token string&quot;&gt;&apos;logger&apos;&lt;/span&gt;
  ActiveRecord::Base.logger &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Logger.new&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;STDOUT&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  ActiveRecord::Base.clear_active_connections&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;
end%&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;Globals&lt;/h3&gt;
&lt;p&gt;If you are bug hunting deep inside a gem or rails internals, and are trying to pry into a module that is loaded many times before it hits the buggy line of code, a simple &lt;code class=&quot;language-text&quot;&gt;binding.pry&lt;/code&gt; will have you stepping through an impossible amount of setup. Try setting a global variable to &lt;code class=&quot;language-text&quot;&gt;true&lt;/code&gt; right before the buggy line, and &lt;code class=&quot;language-text&quot;&gt;binding.pry&lt;/code&gt; on that condition:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;➜  api_playground  zeus &lt;span class=&quot;token builtin class-name&quot;&gt;test&lt;/span&gt; /Users/keighty/api_playground/test/models/user_test.rb -n &lt;span class=&quot;token string&quot;&gt;&quot;/test_user_description_has_full_name/&quot;&lt;/span&gt;
Run options: -n /test_user_description_has_full_name/ --seed &lt;span class=&quot;token number&quot;&gt;28811&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# Running:&lt;/span&gt;


From: /Users/keighty/api_playground/app/models/user.rb @ line &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt; User&lt;span class=&quot;token comment&quot;&gt;#full_name:&lt;/span&gt;

    &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;: def full_name
    &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;:   &lt;span class=&quot;token variable&quot;&gt;$bedug&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;
    &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;:   &lt;span class=&quot;token string&quot;&gt;&quot;#{first_name} #{last_name}&quot;&lt;/span&gt;
    &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;:   binding.pry &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$bedug&lt;/span&gt;
    &lt;span class=&quot;token number&quot;&gt;6&lt;/span&gt;: end&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;A global will maintain its state no matter how many times the code is loaded, so be sure to set the variable to false if you are stepping past the first break.&lt;/p&gt;
&lt;h3&gt;Caller&lt;/h3&gt;
&lt;p&gt;Calling &lt;code class=&quot;language-text&quot;&gt;caller&lt;/code&gt; at a pry prompt will output the current execution stack:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;[1] pry(#&amp;lt;User&gt;)&gt; caller
=&gt; [&quot;/usr/local/var/rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/pry-0.10.1/lib/pry/pry_instance.rb:355:in `eval&apos;&quot;,
 &quot;/usr/local/var/rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/pry-0.10.1/lib/pry/pry_instance.rb:355:in `evaluate_ruby&apos;&quot;,
 &quot;/usr/local/var/rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/pry-0.10.1/lib/pry/pry_instance.rb:323:in `handle_line&apos;&quot;,
 &quot;/usr/local/var/rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/pry-0.10.1/lib/pry/pry_instance.rb:243:in `block (2 levels) in eval&apos;&quot;,
 &quot;/usr/local/var/rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/pry-0.10.1/lib/pry/pry_instance.rb:242:in `catch&apos;&quot;,
 &quot;/usr/local/var/rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/pry-0.10.1/lib/pry/pry_instance.rb:242:in `block in eval&apos;&quot;,
 &quot;/usr/local/var/rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/pry-0.10.1/lib/pry/pry_instance.rb:241:in `catch&apos;&quot;,
 &quot;/usr/local/var/rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/pry-0.10.1/lib/pry/pry_instance.rb:241:in `eval&apos;&quot;,
 &quot;/usr/local/var/rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/pry-0.10.1/lib/pry/repl.rb:77:in `block in repl&apos;&quot;,
 &quot;/usr/local/var/rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/pry-0.10.1/lib/pry/repl.rb:67:in `loop&apos;&quot;,
 &quot;/usr/local/var/rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/pry-0.10.1/lib/pry/repl.rb:67:in `repl&apos;&quot;,
 &quot;/usr/local/var/rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/pry-0.10.1/lib/pry/repl.rb:38:in `block in start&apos;&quot;,
 &quot;/usr/local/var/rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/pry-0.10.1/lib/pry/input_lock.rb:61:in `call&apos;&quot;,
 &quot;/usr/local/var/rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/pry-0.10.1/lib/pry/input_lock.rb:61:in `__with_ownership&apos;&quot;,
 &quot;/usr/local/var/rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/pry-0.10.1/lib/pry/input_lock.rb:79:in `with_ownership&apos;&quot;,
 &quot;/usr/local/var/rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/pry-0.10.1/lib/pry/repl.rb:38:in `start&apos;&quot;,
 &quot;/usr/local/var/rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/pry-0.10.1/lib/pry/repl.rb:15:in `start&apos;&quot;,
 &quot;/usr/local/var/rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/pry-0.10.1/lib/pry/pry_class.rb:169:in `start&apos;&quot;,
 &quot;/usr/local/var/rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/pry-0.10.1/lib/pry/core_extensions.rb:43:in `pry&apos;&quot;,
 &quot;/Users/keighty/api_playground/app/models/user.rb:5:in `full_name&apos;&quot;,
 &quot;/Users/keighty/api_playground/test/models/user_test.rb:6:in `test_user_description_has_full_name&apos;&quot;,
 &quot;/usr/local/var/rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/minitest-5.5.1/lib/minitest/test.rb:108:in `block (3 levels) in run&apos;&quot;,
 &quot;/usr/local/var/rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/minitest-5.5.1/lib/minitest/test.rb:206:in `capture_exceptions&apos;&quot;,
 &quot;/usr/local/var/rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/minitest-5.5.1/lib/minitest/test.rb:105:in `block (2 levels) in run&apos;&quot;,
 &quot;/usr/local/var/rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/minitest-5.5.1/lib/minitest/test.rb:258:in `time_it&apos;&quot;,
 &quot;/usr/local/var/rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/minitest-5.5.1/lib/minitest/test.rb:104:in `block in run&apos;&quot;,
 &quot;/usr/local/var/rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/minitest-5.5.1/lib/minitest.rb:327:in `on_signal&apos;&quot;,
:&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;caller&lt;/code&gt; is a &lt;a href=&quot;http://www.ruby-doc.org/core-2.2.0/Kernel.html#method-i-caller&quot;&gt;Kernel method&lt;/a&gt;. Pass a start line and a line limit to truncate the stack:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;[11] pry(#&amp;lt;User&gt;)&gt; caller(20, 5)
=&gt; [&quot;/Users/keighty/api_playground/app/models/user.rb:5:in `full_name&apos;&quot;,
 &quot;/Users/keighty/api_playground/test/models/user_test.rb:6:in `test_user_description_has_full_name&apos;&quot;,
 &quot;/usr/local/var/rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/minitest-5.5.1/lib/minitest/test.rb:108:in `block (3 levels) in run&apos;&quot;,
 &quot;/usr/local/var/rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/minitest-5.5.1/lib/minitest/test.rb:206:in `capture_exceptions&apos;&quot;,
 &quot;/usr/local/var/rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/minitest-5.5.1/lib/minitest/test.rb:105:in `block (2 levels) in run&apos;&quot;]&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The first 20 or so lines are usually from the pry session so they are easily ignored. I can see that the User.full_name method is being called from my test — a trivial case, but it comes in very handy when debugging a deeper stack.&lt;/p&gt;
&lt;h3&gt;Errors&lt;/h3&gt;
&lt;p&gt;When models have many association dependencies, satisfying the validations of many dependencies can be tricky without descriptive errors. In Rails 3.2, the error storage was changed from an &lt;a href=&quot;http://www.rubydoc.info/docs/rails/3.0.0/ActiveModel/Errors&quot;&gt;OrderedHash&lt;/a&gt; to a first class ruby object in &lt;a href=&quot;http://www.rubydoc.info/docs/rails/3.2.8/ActiveModel/Errors&quot;&gt;ActiveModel&lt;/a&gt;. While the interface has changed, its value remains:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;[1] pry(main)&gt; user = User.create
=&gt; #&amp;lt;User:0x007fa054525318
 id: nil,
 first_name: nil,
 last_name: nil,
 email: nil,
 created_at: nil,
 updated_at: nil&gt;

# Why does my object not have an id?

[2] pry(main)&gt; user.errors
=&gt; #&amp;lt;ActiveModel::Errors:0x007fa05451fda0
 @base=
  #&amp;lt;User:0x007fa054525318
   id: nil,
   first_name: nil,
   last_name: nil,
   email: nil,
   created_at: nil,
   updated_at: nil&gt;,
 @messages={:first_name=&gt;[&quot;can&apos;t be blank&quot;], :last_name=&gt;[&quot;can&apos;t be blank&quot;]}&gt;

[3] pry(main)&gt; user.errors.full_messages
=&gt; [&quot;First name can&apos;t be blank&quot;, &quot;Last name can&apos;t be blank&quot;]

# oooooh... validations&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</content:encoded></item><item><title><![CDATA[scopes and single table inheritance]]></title><description><![CDATA[Single table inheritance (STI) is a way to emulate object-oriented inheritance in a relational database by storing multiple object types in…]]></description><link>http://katieleonard.ca/blog/2015/2015-01-22-scopes-and-single-table-inheritance/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2015/2015-01-22-scopes-and-single-table-inheritance/</guid><pubDate>Thu, 22 Jan 2015 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Single table inheritance (STI) is a way to emulate object-oriented inheritance in a relational database&lt;sup id=&quot;fnref-1&quot;&gt;&lt;a href=&quot;#fn-1&quot; class=&quot;footnote-ref&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; by storing multiple object types in one table, distinguishable by a discriminator column such as &lt;code class=&quot;language-text&quot;&gt;type&lt;/code&gt;. Mixing levels of abstraction may make &lt;code class=&quot;language-text&quot;&gt;join&lt;/code&gt; operations easier, but it also makes other queries more complicated. In Rails 3.2, a query optimization was introduced that had some unintended consequences for STI.&lt;/p&gt;
&lt;!--more--&gt;
&lt;p&gt;A scope represents a narrowing of a database query, and a named scope is syntactic sugar for defining a class method at runtime.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ruby&quot;&gt;&lt;pre class=&quot;language-ruby&quot;&gt;&lt;code class=&quot;language-ruby&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Shirt&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; ActiveRecord&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;Base
  scope &lt;span class=&quot;token symbol&quot;&gt;:in_style&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; where&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&apos;purchase_date &gt;= ?&apos;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Time&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;now &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2.&lt;/span&gt;months&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;PoloShirt&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; Shirt
  scope &lt;span class=&quot;token symbol&quot;&gt;:red&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; where&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token symbol&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&apos;red&apos;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  scope &lt;span class=&quot;token symbol&quot;&gt;:blue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; where&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token symbol&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&apos;blue&apos;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;SweatShirt&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; Shirt
  scope &lt;span class=&quot;token symbol&quot;&gt;:logo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; where&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token symbol&quot;&gt;logo&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&apos;dragon&apos;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;end&lt;/span&gt;

PoloShirt&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;red&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;in_style&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The scope &lt;code class=&quot;language-text&quot;&gt;:in_style&lt;/code&gt; is converted into a class method behind the scenes at runtime, and is defined on the singleton class where the scope was named, not on the caller. While this detail has no consequences for objects outside of an inheritance scheme, it means that when PoloShirt invokes the &lt;code class=&quot;language-text&quot;&gt;:in_style&lt;/code&gt; scope, the class method is declared on Shirt, not PoloShirt.&lt;/p&gt;
&lt;p&gt;Here is where the history lesson begins. Scopes have evolved in Rails, and while they remain syntactic sugar for definition class methods, the details, method signature, and sql translation have differed dramatically.&lt;/p&gt;
&lt;p&gt;In &lt;a href=&quot;http://www.rubydoc.info/docs/rails/3.0.0/ActiveRecord/NamedScope/ClassMethods:scope&quot;&gt;Rails 3.0&lt;/a&gt;, the scope method accepts a name, scope_options, and optional block. Scopes are directly translated into class methods behind the scenes, and the consequences of chaining scopes are the same as chaining queries, just nicer looking.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;PoloShirt.red.in_style.to_sql
=&gt; SELECT * from shirts WHERE color = &apos;red&apos; where type = &apos;PoloShirt&apos; where purchase_date &gt;= 1417102745 where type IN (&apos;PoloShirt&apos;, &apos;Sweatshirt&apos;)&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Notice the implicit &lt;code class=&quot;language-text&quot;&gt;where&lt;/code&gt; clause in STI. The &lt;code class=&quot;language-text&quot;&gt;:red&lt;/code&gt; scope, declared on PoloShirt has &lt;code class=&quot;language-text&quot;&gt;where type = &apos;PoloShirt&apos;&lt;/code&gt;, and the &lt;code class=&quot;language-text&quot;&gt;:in_style&lt;/code&gt; scope, declared on Shirt, has &lt;code class=&quot;language-text&quot;&gt;where type IN (&apos;PoloShirt&apos;, &apos;Sweatshirt&apos;)&lt;/code&gt;. The second &lt;code class=&quot;language-text&quot;&gt;where&lt;/code&gt; clause will have no impact on the query results, because they are already scoped to ‘PoloShirt’. It is this behaviour that evolves over time.&lt;/p&gt;
&lt;p&gt;The first jump in &lt;code class=&quot;language-text&quot;&gt;scope&lt;/code&gt; evolution is in &lt;a href=&quot;http://www.rubydoc.info/docs/rails/3.2.8/ActiveRecord/Scoping/Named/ClassMethods:scope&quot;&gt;Rails 3.2&lt;/a&gt;, where the scope_options can include lambdas. Passing a lambda is a big advantage in that it allows the scope to be re-evaluated each time it is called. Unfortunately the implementation also remixes the query parameters of all chained scopes before evaluation:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;In nested scopings, all previous parameters are overwritten by the innermost rule, with the exception of &lt;code class=&quot;language-text&quot;&gt;where&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;includes&lt;/code&gt;, and &lt;code class=&quot;language-text&quot;&gt;joins&lt;/code&gt; operations in Relation, which are merged.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;PoloShirt.red.in_style.to_sql
=&gt; SELECT * from shirts where color = &apos;red&apos; where purchase_date &gt;= 1417102745 where type IN (&apos;PoloShirt&apos;, &apos;Sweatshirt&apos;)&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The first &lt;code class=&quot;language-text&quot;&gt;where type =&lt;/code&gt; clause is merged with the last &lt;code class=&quot;language-text&quot;&gt;where type IN&lt;/code&gt; clause. The results of this query will no longer be scoped to PoloShirts, but will return all &lt;code class=&quot;language-text&quot;&gt;red.in_style&lt;/code&gt; Shirts of any type. Bad news for STI.&lt;/p&gt;
&lt;p&gt;The good news is that this behaviour is &lt;a href=&quot;https://github.com/rails/rails/commit/cd26b6ae&quot;&gt;fixed&lt;/a&gt; in &lt;a href=&quot;http://www.rubydoc.info/docs/rails/4.0.0/ActiveRecord/Scoping/Named/ClassMethods#scope-instance_method&quot;&gt;Rails 4.0&lt;/a&gt;. The latest evolution of scopes no longer allow you to pass a non-callable object (like a hash), and all scopes are merged using AND.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;PoloShirt.red.in_style.to_sql
=&gt; SELECT * from shirts where color = &apos;red&apos; where purchase_date &gt;= 1417102745 where type = &apos;PoloShirt&apos; AND type IN (&apos;PoloShirt&apos;, &apos;Sweatshirt&apos;)&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Our &lt;code class=&quot;language-text&quot;&gt;red.in_style&lt;/code&gt; query is once again scoped to the right level of the inheritance heirarchy. Named scopes are chainable and lazy-evaluated, making them a powerful query-building tool that can be difficult to troubleshoot — especially when they are mixed with single-table inheritance.&lt;/p&gt;
&lt;div class=&quot;footnotes&quot;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&quot;fn-1&quot;&gt;
&lt;p&gt;&lt;a href=&quot;http://en.wikipedia.org/wiki/Single_Table_Inheritance&quot;&gt;http://en.wikipedia.org/wiki/Single_Table_Inheritance&lt;/a&gt;&lt;/p&gt;
&lt;a href=&quot;#fnref-1&quot; class=&quot;footnote-backref&quot;&gt;↩&lt;/a&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</content:encoded></item><item><title><![CDATA[Our healthcare system is a legacy application]]></title><description><![CDATA[One of my favourite blogs is Brain Pickings, written by Maria Popova, which is a collection of thoughts spanning art, science, psychology…]]></description><link>http://katieleonard.ca/blog/2015/2015-01-20-healthcare-is-a-legacy-application/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2015/2015-01-20-healthcare-is-a-legacy-application/</guid><pubDate>Tue, 20 Jan 2015 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;One of my favourite blogs is &lt;a href=&quot;http://www.brainpickings.org&quot;&gt;Brain Pickings&lt;/a&gt;, written by Maria Popova, which is a collection of thoughts spanning art, science, psychology, and almost every other subject I read voraciously. Recently I stumbled upon &lt;a href=&quot;http://www.brainpickings.org/2014/09/17/sherwin-nuland-how-we-die/&quot;&gt;this gem&lt;/a&gt;, Sherwin B. Nuland’s &lt;a href=&quot;http://www.amazon.com/How-We-Die-Sherwin-Nuland-ebook/dp/B004CJ8QCE&quot;&gt;&lt;em&gt;How We Die&lt;/em&gt;&lt;/a&gt;&lt;sup id=&quot;fnref-1&quot;&gt;&lt;a href=&quot;#fn-1&quot; class=&quot;footnote-ref&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;. It is a raw look at the biological processes that occur at the end of life, which resonated with me on many levels.&lt;/p&gt;
&lt;!--more--&gt;
&lt;p&gt;The biologist within was fascinated by Nuland’s ability to reduce the “ten thousand several doors for men to take their exits”&lt;sup id=&quot;fnref-2&quot;&gt;&lt;a href=&quot;#fn-2&quot; class=&quot;footnote-ref&quot;&gt;2&lt;/a&gt;&lt;/sup&gt; to the same basic process of poor oxygenation and nutrition of vital tissues resulting in organ failure. Whether the process is long or slow, instigated by heart disease, Alzheimer’s disease, AIDS, accident, or old age, the end must come when the heart stops nourishing the brain.&lt;/p&gt;
&lt;p&gt;As a Clinical Professor of Surgery at Yale University, Nuland became intimate with death and its increasingly dehumanizing circumstances. Life’s final chapter has become invisible to most of us. It is likely to be carried out in an intensive care unit, the person reduced to data on a screen, and the advancing disease perceived as a failure of management rather than a natural and inevitable process. He shares the lessons he learned about providing true patient care rather than solving a biological riddle (sometimes the best patient care is no care at all).&lt;/p&gt;
&lt;p&gt;Most importantly, he calls attention to the deplorable state of healthcare today, where the “provider” has usurped the role of the physician:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;[Our] present system of in-hospital care… has simply accreted by the constant piling on or insinuation of patches of not necessarily compatible structure to an edifice already jerry-built of competing needs.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Sounds remarkably like a long-lived legacy application that is impossibly complex and difficult to work in. The healthcare system is in need of a great refactoring, which isn’t without precedent (read about Abraham Flexner’s report &lt;a href=&quot;https://books.google.com/books?id=lxgTAAAAYAAJ&amp;#x26;printsec=frontcover&amp;#x26;dq=inauthor:%22Abraham+Flexner%22&amp;#x26;hl=en&amp;#x26;sa=X&amp;#x26;ei=rmXAVIvHLYKYoQSM5YGgDQ&amp;#x26;ved=0CCwQ6AEwAg#v=onepage&amp;#x26;q&amp;#x26;f=false&quot;&gt;Medical Education in the United States and Canada&lt;/a&gt; that started the movement to raise “American medical education… to the highest [status] in the civilized world”&lt;sup id=&quot;fnref-3&quot;&gt;&lt;a href=&quot;#fn-3&quot; class=&quot;footnote-ref&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;)&lt;/p&gt;
&lt;p&gt;&lt;em&gt;How We Die&lt;/em&gt; won the National Book Award, was a finalist for the Pulitzer Prize, and perched atop the New York Times’ bestseller list for more than thirty weeks. This book answers a question we have all asked at some point — what will it be like to die? A hope many of us share is to have a dignified death with little suffering for ourselves and our families, but reflecting on his many years and experiences with death, Nuland has found that&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;the greatest dignity to be found in death is the dignity of the life that preceded it. This is a form of hope we can all achieve, and it is the most abiding of all. Hope resides in the meaning of what our lives have been.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div class=&quot;footnotes&quot;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&quot;fn-1&quot;&gt;
&lt;p&gt;Nuland, Sherwin B. (2014-06-25). &lt;em&gt;How We Die: Reflections on Life’s Final Chapter&lt;/em&gt;. Kindle Edition&lt;/p&gt;
&lt;a href=&quot;#fnref-1&quot; class=&quot;footnote-backref&quot;&gt;↩&lt;/a&gt;
&lt;/li&gt;
&lt;li id=&quot;fn-2&quot;&gt;
&lt;p&gt;Webster, John. (1612) &lt;em&gt;The Duchess of Malfi&lt;/em&gt;&lt;/p&gt;
&lt;a href=&quot;#fnref-2&quot; class=&quot;footnote-backref&quot;&gt;↩&lt;/a&gt;
&lt;/li&gt;
&lt;li id=&quot;fn-3&quot;&gt;
&lt;p&gt;Flenxer, Abraham. (1910). &lt;em&gt;Medical Education in the United States and Canada&lt;/em&gt;.&lt;/p&gt;
&lt;a href=&quot;#fnref-3&quot; class=&quot;footnote-backref&quot;&gt;↩&lt;/a&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</content:encoded></item><item><title><![CDATA[objects vs data structures]]></title><description><![CDATA[“It is impossible to create an abstraction unknowingly or by accident,” says Sandi Metz in Practical Object Oriented Design in Ruby. An…]]></description><link>http://katieleonard.ca/blog/2015/2015-01-18-objects-vs-data-structures/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2015/2015-01-18-objects-vs-data-structures/</guid><pubDate>Sun, 18 Jan 2015 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;“It is impossible to create an abstraction unknowingly or by accident,” says Sandi Metz in &lt;a href=&quot;http://www.amazon.com/Practical-Object-Oriented-Design-Ruby-Addison-Wesley/dp/0321721330/ref=sr_1_1?ie=UTF8&amp;#x26;qid=1421723392&amp;#x26;sr=8-1&amp;#x26;keywords=practical+object+oriented+design+in+ruby&quot;&gt;&lt;em&gt;Practical Object Oriented Design in Ruby&lt;/em&gt;&lt;/a&gt;. An abstraction is a common, stable quality, such that you would find in a java interface. An interface is an idea that cannot be made concrete, but contains behaviour &lt;a href=&quot;http://en.wikipedia.org/wiki/Interface_%28Java%29&quot;&gt;encoding similarities&lt;/a&gt; which objects might share. Even the definition of abstraction is abstract, and it wasn’t until I read Robert C. Martin’s chapter on Objects and Data Structures in &lt;a href=&quot;http://www.amazon.com/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882&quot;&gt;&lt;em&gt;Clean Code&lt;/em&gt;&lt;/a&gt; that I really started to understand them.&lt;/p&gt;
&lt;!--more--&gt;
&lt;h3&gt;What is a data structure&lt;/h3&gt;
&lt;p&gt;A data structure is a class that exposes its data to the public. It should have no meaningful behaviour, and can be characterized by a set of attributes along with getters and setters.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ruby&quot;&gt;&lt;pre class=&quot;language-ruby&quot;&gt;&lt;code class=&quot;language-ruby&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Point1&lt;/span&gt;
  attr_accessor &lt;span class=&quot;token symbol&quot;&gt;:x&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token symbol&quot;&gt;:y&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token symbol&quot;&gt;:z&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;end&lt;/span&gt;

p &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Point1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt;
p&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;x &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;
p&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;y &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;
p&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;z &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;
p&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In this example, a Point is defined as an object at some location on a coordinate grid of some kind. That sounds abstract enough: you can create a point, access all of the point’s data, and set its location along each axis independently. You have an instance of a point, but it is not an abstraction of a point — it is a data structure. {“Hiding implementation is not about putting a layer of functions between the variables. It is about abstractions.“}
Adding an initializer that sets each variable, or a &lt;code class=&quot;language-text&quot;&gt;to_s&lt;/code&gt; method for getting a pretty output, would not make the Point1 class any more an abstraction of a position in space. To make an abstraction you can’t just use getters and setters — you have to think about how you are representing the data.&lt;/p&gt;
&lt;h3&gt;What is an object&lt;/h3&gt;
&lt;p&gt;An object hides its data behind abstractions. A Point is not defined by its &lt;code class=&quot;language-text&quot;&gt;[@x, @y, @z]&lt;/code&gt;, but by its location in space. If space is a coordinate system, it could be 2- or 3-dimensional.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;class Point2
  def initialize(x, y, z = nil)
    set_location(x, y, z)
  end

  def to_s
    &quot;(#{[@x, @y, @z].compact.join(&apos;,&apos;)})&quot;
  end
  alias_method :location, :to_s

  def set_location(x, y, z = nil)
    @x = x
    @y = y
    @z = z
    location
  end
  private :set_location

  alias_method :move_point, :set_location
  public :move_point

end

p = Point2.new(1, 1)
p.move_point(2, 3)
p.move_point(2, 3, 7)&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;A point cannot exist separate from it’s coordinates, and coordinates cannot exist or be altered without using the abstraction of moving in space.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“We do not want to expose the details of our data. Rather we want to express our data in abstract terms. This is not merely accomplished by using interfaces and/or getters and setters. Serious thought needs to be put into the best way to represent the data that an object contains.”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;— Martin&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This is why &lt;a href=&quot;http://blog.codeclimate.com/blog/2012/10/17/7-ways-to-decompose-fat-activerecord-models/&quot;&gt;fat models are an anti-pattern in Rails&lt;/a&gt;. ActiveRecord makes an object out of a data structure, and adding behaviour beyond data validation makes the model a hybrid data object. &lt;a href=&quot;http://railscasts.com/episodes/398-service-objects&quot;&gt;Service Objects&lt;/a&gt; are abstractions of model behaviour (pun intended).&lt;/p&gt;
&lt;p&gt;Now I know what an abstraction is, and I understand that simply extracting methods into interfaces doesn’t magically make an abstraction. As Metz says, “good design naturally progresses toward small independent objects that rely on abstractions.” An object is more than a data structure; it is an idea and it must be applied deliberately.&lt;/p&gt;
&lt;!-- resources
http://www.cgore.com/programming/ruby/public-aliases-of-private-methods.lisp
--&gt;
&lt;!-- resources
http://railscasts.com/episodes/398-service-objects
http://blog.codeclimate.com/blog/2012/10/17/7-ways-to-decompose-fat-activerecord-models/
--&gt;</content:encoded></item><item><title><![CDATA[cleaning the campground]]></title><description><![CDATA[If you work in a code base with many other contributors, you may have learned the scouting philosophy to “leave the campground cleaner than…]]></description><link>http://katieleonard.ca/blog/2015/2015-01-10-cleaning-the-campground/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2015/2015-01-10-cleaning-the-campground/</guid><pubDate>Sat, 10 Jan 2015 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;If you work in a code base with many other contributors, you may have learned the scouting philosophy to “leave the campground cleaner than you found it.” Sometimes the code you are working in can seem so entangled and complex that it is hard to know where to begin, but &lt;a href=&quot;http://www.amazon.com/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882/ref=sr_1_1?ie=UTF8&amp;#x26;qid=1420928385&amp;#x26;sr=8-1&amp;#x26;keywords=clean+code&quot;&gt;Robert C. Martin’s foundational book, *Clean Code&lt;/a&gt;*, tells us that very small changes can improve the readability and maintainability of a piece of code.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“It is not enough to write the code well. The code has to be &lt;em&gt;kept clean&lt;/em&gt; over time.”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;!--more--&gt;
&lt;p&gt;&lt;a href=&quot;http://en.wikipedia.org/wiki/Software_rot&quot;&gt;Code rot&lt;/a&gt; happens to every well-intentioned but long-lived code base, and it can happen either by neglect or by constant development. Neglected software will suffer a gradual deterioration in performance and responsiveness over time. Security vulnerabilities and incompatibilities aside, as new applications are built in newer and faster frameworks, your application will perform poorly in comparison. If your software is actively developed it will be modified, and as it is modified it’s complexity will increase. {“Add in more developers, each with different coding styles, and before long you will find your code to be impenetrably complex and impossible to modify.“}&lt;/p&gt;
&lt;p&gt;There is hope for your legacy application, as long as you establish a culture of constant small improvements:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Change one variable name for the better&lt;/li&gt;
&lt;li&gt;Break one large function into two or more smaller ones.&lt;/li&gt;
&lt;li&gt;Eliminate one small bit of duplication&lt;/li&gt;
&lt;li&gt;Clean up one composite if statement.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;That last one is a bit like low-hanging fruit. Take this complex if statement in &lt;a href=&quot;https://github.com/rack/rack/blob/rack-1.5/lib/rack/deflater.rb#L30-L33&quot;&gt;Rack::Deflater#call&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;def call
  ...

  # Skip compressing empty entity body responses and responses with
  # no-transform set.
  if Utils::STATUS_WITH_NO_ENTITY_BODY.include?(status) ||
      headers[&apos;Cache-Control&apos;].to_s =~ /\bno-transform\b/ ||
     (headers[&apos;Content-Encoding&apos;] &amp;amp;&amp;amp; headers[&apos;Content-Encoding&apos;] !~ /\bidentity\b/)
    return [status, headers, body]
  end
  ...&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The comment attempts to explain what the code cannot: skip response compression under certain conditions. The intention could easily be described by extracting both the comment and the if statement to a method:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;def call
  ...
  if skip_compression?
    return [status, headers, body]
  end
  ...
end

private

# Skip compressing empty entity body responses and responses with
# no-transform set.
def skip_compression?
  Utils::STATUS_WITH_NO_ENTITY_BODY.include?(status) ||
    headers[&apos;Cache-Control&apos;].to_s =~ /\bno-transform\b/ ||
   (headers[&apos;Content-Encoding&apos;] &amp;amp;&amp;amp; headers[&apos;Content-Encoding&apos;] !~ /\bidentity\b/)
end&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;While the &lt;code class=&quot;language-text&quot;&gt;if&lt;/code&gt; statement itself is not much better, at least &lt;code class=&quot;language-text&quot;&gt;#call&lt;/code&gt; is a little more readable. Fight against code rot while building new features in a legacy code base by making small improvements where you can.&lt;/p&gt;
&lt;!-- resources
http://en.wikipedia.org/wiki/Software_entropy
--&gt;</content:encoded></item><item><title><![CDATA[#dup vs #clone in Ruby and rails]]></title><description><![CDATA[I was recently fixing a failing test and discovered that Ruby and Rails implement  and  in confusing and occasionally opposite ways. In…]]></description><link>http://katieleonard.ca/blog/2015/2015-01-10-number-dup-vs-number-clone-in-ruby-and-rails/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2015/2015-01-10-number-dup-vs-number-clone-in-ruby-and-rails/</guid><pubDate>Sat, 10 Jan 2015 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I was recently fixing a failing test and discovered that Ruby and Rails implement &lt;code class=&quot;language-text&quot;&gt;#clone&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;#dup&lt;/code&gt; in confusing and occasionally opposite ways.&lt;/p&gt;
&lt;!--more--&gt;
&lt;h3&gt;In Rails &lt;code class=&quot;language-text&quot;&gt;#clone&lt;/code&gt; is a less complete copy of an object than &lt;code class=&quot;language-text&quot;&gt;#dup&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;Rails versions have flip-flopped on how to implement &lt;code class=&quot;language-text&quot;&gt;#clone&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;#dup&lt;/code&gt;, and there is ambiguity in how Rails defines “shallow”. In Rails 4.0, &lt;a href=&quot;https://github.com/rails/rails/blob/4-0-stable/activerecord/lib/active_record/core.rb#L217-L220&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;#clone&lt;/code&gt; is a shallow copy&lt;/a&gt; of an ActiveRecord object. “Shallow” in this context means that the &lt;code class=&quot;language-text&quot;&gt;clone&lt;/code&gt; shares attributes with the &lt;code class=&quot;language-text&quot;&gt;original&lt;/code&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Identical to Ruby’s clone method.  This is a “shallow” copy.  Be warned that your attributes are not copied. That means that modifying attributes of the clone will modify the original, since they will both point to the same attributes hash. If you need a copy of your attributes hash, please use the #dup method.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;However, &lt;a href=&quot;https://github.com/rails/rails/blob/4-0-stable/activerecord/lib/active_record/core.rb#L234-L240&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;#dup&lt;/code&gt; is also described as a shallow copy&lt;/a&gt;. “Shallow” in this context means that while the dup does not share attributes with the original, it does share associations.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Duped objects have no id assigned and are treated as new records. Note that this is a “shallow” copy as it copies the object’s attributes only, not its associations. The extent of a “deep” copy is application specific and is therefore left to the application to implement according to its need.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h4&gt;&lt;code class=&quot;language-text&quot;&gt;clone&lt;/code&gt; vs &lt;code class=&quot;language-text&quot;&gt;dup&lt;/code&gt; in Rails:&lt;/h4&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;pry&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; original &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; User.find&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  User Load &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;.7ms&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;  SELECT  &lt;span class=&quot;token string&quot;&gt;&quot;users&quot;&lt;/span&gt;.* FROM &lt;span class=&quot;token string&quot;&gt;&quot;users&quot;&lt;/span&gt; WHERE &lt;span class=&quot;token string&quot;&gt;&quot;users&quot;&lt;/span&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;id&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; ? LIMIT &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;  &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;id&quot;&lt;/span&gt;, &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;#&amp;lt;User id: 3, first_name: &quot;katie&quot;, last_name: &quot;leonard&quot;, email: nil, created_at: &quot;2015-01-10 17:37:00&quot;, updated_at: &quot;2015-01-10 17:37:00&quot;&gt;&lt;/span&gt;

pry&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; clone_copy &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; original.clone
&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;#&amp;lt;User id: 3, first_name: &quot;katie&quot;, last_name: &quot;leonard&quot;, email: nil, created_at: &quot;2015-01-10 17:37:00&quot;, updated_at: &quot;2015-01-10 17:37:00&quot;&gt;&lt;/span&gt;

pry&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; dup_copy &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; original.dup
&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;#&amp;lt;User id: nil, first_name: &quot;katie&quot;, last_name: &quot;leonard&quot;, email: nil, created_at: nil, updated_at: nil&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Note that the &lt;code class=&quot;language-text&quot;&gt;clone_copy&lt;/code&gt; is an exact copy of the original (same &lt;code class=&quot;language-text&quot;&gt;user.id&lt;/code&gt;) and the &lt;code class=&quot;language-text&quot;&gt;dup_copy&lt;/code&gt; is a new record (&lt;code class=&quot;language-text&quot;&gt;user.id&lt;/code&gt; = nil). Any changes made to the &lt;code class=&quot;language-text&quot;&gt;clone_copy&lt;/code&gt; will be changed in the &lt;code class=&quot;language-text&quot;&gt;original&lt;/code&gt;, but any changes to the &lt;code class=&quot;language-text&quot;&gt;dup_copy&lt;/code&gt; attributes will remain isolated.&lt;/p&gt;
&lt;h3&gt;In Ruby &lt;code class=&quot;language-text&quot;&gt;#clone&lt;/code&gt; is a more complete copy of an object than &lt;code class=&quot;language-text&quot;&gt;#dup&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;With simple classes, &lt;code class=&quot;language-text&quot;&gt;clone()&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;dup()&lt;/code&gt; behave identically:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;irb&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; class User
irb&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;   attr_accessor :first_name, :last_name, :email
irb&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;   def initialize&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;options&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
irb&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;     @first_name &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; options&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;:first_name&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
irb&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;     @last_name  &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; options&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;:last_name&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
irb&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;     @email      &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; options&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;:email&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
irb&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;   end
irb&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; end
&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; :initialize

irb&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; original &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; User.new&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;first_name: &lt;span class=&quot;token string&quot;&gt;&quot;katie&quot;&lt;/span&gt;, last_name: &lt;span class=&quot;token string&quot;&gt;&quot;leonard&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;#&amp;lt;User:0x007fd7e98e0aa8 @first_name=&quot;katie&quot;, @last_name=&quot;leonard&quot;, @email=nil&gt;&lt;/span&gt;

irb&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; cloned_copy &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; original.clone
&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;#&amp;lt;User:0x007fd7e98c87c8 @first_name=&quot;katie&quot;, @last_name=&quot;leonard&quot;, @email=nil&gt;&lt;/span&gt;

irb&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; dup_copy &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; original.dup
&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;#&amp;lt;User:0x007fd7e98b24a0 @first_name=&quot;katie&quot;, @last_name=&quot;leonard&quot;, @email=nil&gt;&lt;/span&gt;

irb&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; cloned_copy.first_name &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;foo&quot;&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;foo&quot;&lt;/span&gt;

irb&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; original.first_name
&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;katie&quot;&lt;/span&gt;

irb&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; dup_copy.first_name
&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;katie&quot;&lt;/span&gt;

irb&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; dup_copy.first_name &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;bar&quot;&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;bar&quot;&lt;/span&gt;

irb&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; original.first_name
&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;katie&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;clone()&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;dup()&lt;/code&gt; function the same way!&lt;/p&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;clone()&lt;/code&gt; from the &lt;a href=&quot;http://ruby-doc.org/core-2.1.5/Object.html#method-i-clone&quot;&gt;Ruby docs&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Produces a shallow copy of obj — the instance variables of obj are copied, but not the objects they reference. Copies the frozen and tainted state of obj. See also the discussion under Object#dup.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;dup()&lt;/code&gt; from the &lt;a href=&quot;http://ruby-doc.org/core-2.1.5/Object.html#method-i-dup&quot;&gt;Ruby docs&lt;/a&gt; looks suspiciously like the docs for &lt;code class=&quot;language-text&quot;&gt;clone()&lt;/code&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Produces a shallow copy of obj — the instance variables of obj are copied, but not the objects they reference. dup copies the tainted state of obj. This method may have class-specific behavior. If so, that behavior will be documented under the #initialize_copy method of the class.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This deserves further clarification:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;In general, clone and dup may have different semantics in descendant classes. While clone is used to duplicate an object, including its internal state, dup typically uses the class of the descendant object to create the new instance. When using dup any modules that the object has been extended with will not be copied.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;To paraphrase, &lt;code class=&quot;language-text&quot;&gt;#dup&lt;/code&gt; will act like &lt;code class=&quot;language-text&quot;&gt;#clone&lt;/code&gt;, but without the original’s singleton class (ergo a “shallower” copy).&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;irb&gt; class User
irb&gt; attr_accessor :first_name, :last_name, :email
irb&gt;   def initialize(options={})
irb&gt;     @first_name = options[:first_name]
irb&gt;     @last_name  = options[:last_name]
irb&gt;     @email      = options[:email]
irb&gt;   end
irb&gt; end
=&gt; :initialize

irb&gt; module Crunchy
irb&gt;   def bacon
irb&gt;     &quot;bacon&quot;
irb&gt;   end
irb&gt; end
=&gt; :bacon

irb&gt; a = User.new(first_name: &quot;katie&quot;, last_name: &quot;leonard&quot;)
=&gt; #&amp;lt;User:0x007fd7e8882490 @first_name=&quot;katie&quot;, @last_name=&quot;leonard&quot;, @email=nil&gt;

irb&gt; a.extend(Crunchy)
=&gt; #&amp;lt;User:0x007fd7e8882490 @first_name=&quot;katie&quot;, @last_name=&quot;leonard&quot;, @email=nil&gt;

irb&gt; a.bacon
=&gt; &quot;bacon&quot;

irb&gt; b = a.clone
=&gt; #&amp;lt;User:0x007fd7e8843060 @first_name=&quot;katie&quot;, @last_name=&quot;leonard&quot;, @email=nil&gt;

irb&gt; b.bacon
=&gt; &quot;bacon&quot;

irb&gt; c = a.dup
=&gt; #&amp;lt;User:0x007fd7e98f05c0 @first_name=&quot;katie&quot;, @last_name=&quot;leonard&quot;, @email=nil&gt;

irb&gt; c.bacon
NoMethodError: undefined method `bacon&apos; for #&amp;lt;User:0x007fd7e98f05c0&gt;
        from (irb):101
        from /usr/local/var/rbenv/versions/2.1.5/bin/irb:11:in `&amp;lt;main&gt;&apos;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;There are subtle differences between &lt;code class=&quot;language-text&quot;&gt;#clone&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;#dup&lt;/code&gt; in Ruby, and less subtle differences in Rails (depending on your version). Take care that the object you want is the object you get.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[TDD and the senior software engineer]]></title><description><![CDATA[Many developers embrace test-driven development (TDD) as an ideal but rarely put it into practice. I often find myself writing code that…]]></description><link>http://katieleonard.ca/blog/2015/2015-01-04-the-senior-software-engineer/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2015/2015-01-04-the-senior-software-engineer/</guid><pubDate>Sun, 04 Jan 2015 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Many developers embrace test-driven development (TDD) as an ideal but rarely put it into practice. I often find myself writing code that works and then writing tests that exercise it to ensure that its behaviour doesn’t break when changes are made. Writing tests first is a great way to organize your approach to solving a problem, and in &lt;a href=&quot;http://www.amazon.com/Senior-Software-Engineer-Practices-Effective/dp/0990702804/ref=sr_1_1?ie=UTF8&amp;#x26;qid=1420403139&amp;#x26;sr=8-1&amp;#x26;keywords=on+being+a+senior+engineer&quot;&gt;&lt;strong&gt;The Senior Software Engineer&lt;/strong&gt;&lt;/a&gt;, David Copeland describes how TDD will help you grow your career as well.&lt;/p&gt;
&lt;!--more--&gt;
&lt;p&gt;A senior software engineer is efficient, and delivers a quality product in a timely fashion. “Effective problem solvers first spend time understanding the problem space and then design a plan”: documenting feature behaviour in a test suite allows you to plan your implementation. Code maintenance and modification are also more efficient when you have a good test suite. If the code has been built using TDD, its behaviour is already well tested. When someone needs to build on top of your feature, the tests will protect it and eliminate the worry of causing regressions (win-win).&lt;/p&gt;
&lt;p&gt;Explicitly describing your plan in a test suite has another benefit that I had not considered before, and that is making you resilient to interruption. If your plan is not layed out on paper, you are maintaining it all in your head, and you have to hold on to a lot of context in your working memory. Every time you are interrupted, you have to dump things out of your working memory, and reloading the problem space takes time and energy. You won’t suffer interruptions well if reloading the context takes 15 minutes each time. You will become unresponsive as you block out the outside world, trying to maintain your context.&lt;/p&gt;
&lt;p&gt;“TDD can help you structure your coding task so that it has natural breaking points. If you are interrupted while trying to fix a failing test, you know exactly where you can pick the task up again.” If you are interrupted after getting a test to pass you can easily read through your test suite to regain your context and pick up the next task.&lt;/p&gt;
&lt;p&gt;Time and context management are essential skills for becoming a senior software engineer, and I am going to try using test driven development to become more interruptable and more productive.&lt;/p&gt;
&lt;!-- RESOURCES
* http://act-r.psy.cmu.edu/wordpress/wp-content/uploads/2012/12/448preparing.to.resume.pdf
* http://interruptions.net/literature/Fogarty-CHI05-p331-fogarty.pdf
* http://contenthere.net/2012/10/what-it-takes-to-be-a-senior-engineer.html
* http://www.amazon.com/Senior-Software-Engineer-Practices-Effective/dp/0990702804/ref=sr_1_1?ie=UTF8&amp;qid=1420403139&amp;sr=8-1&amp;keywords=on+being+a+senior+engineer
* [The Senior Software Engineer](http://www.amazon.com/Senior-Software-Engineer-Practices-Effective/dp/0990702804/ref=sr_1_1?ie=UTF8&amp;qid=1420403139&amp;sr=8-1&amp;keywords=on+being+a+senior+engineer) by David Bryant Copeland

OUTLINE
Test-driven development can help you grow your career.
1. test-driven development is an ideal that many strive for and few embrace.
2. many developers embrace the ideas of test-driven development, but few practice it rigorously.
3. writing tests is important to delivering quality, robust code, and is essential for writing code that you ever hope to change.
4. did you know that test-driven development can help you grow your career as well?
--&gt;</content:encoded></item><item><title><![CDATA[octopress reloaded]]></title><description><![CDATA[I recently upgraded my home hardware from an Asus 10.1” netbook to a 15” MacBook Pro, and once I adjusted to being able to open more than…]]></description><link>http://katieleonard.ca/blog/2015/2015-01-03-octopress-reloaded/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2015/2015-01-03-octopress-reloaded/</guid><pubDate>Sat, 03 Jan 2015 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I recently upgraded my home hardware from an &lt;a href=&quot;http://www.amazon.com/ASUS-1000HE-10-1-Inch-Black-Netbook/dp/B001QTXL82&quot;&gt;Asus 10.1” netbook&lt;/a&gt; to a &lt;a href=&quot;https://www.apple.com/macbook-pro/&quot;&gt;15” MacBook Pro&lt;/a&gt;, and once I adjusted to being able to open more than one window at a time, I got down to the business of loading my files and projects on the new machine. Thanks to &lt;a href=&quot;https://www.dropbox.com/&quot;&gt;Dropbox&lt;/a&gt; and &lt;a href=&quot;https://github.com/&quot;&gt;Github&lt;/a&gt;, most of that work happens either behind the scenes or as needed. Recreating the right environment for each project is still ongoing, and the first challenge I encountered was reloading my blog — started about two years ago using &lt;a href=&quot;http://octopress.org/&quot;&gt;Octopress&lt;/a&gt;.&lt;/p&gt;
&lt;!--more--&gt;
&lt;p&gt;Octopress is an awesome framework built on &lt;a href=&quot;http://jekyllrb.com/&quot;&gt;jekyll&lt;/a&gt;. The learning curve for getting started with jekyll was a little steep (liquid layouts, yaml, not to mention design and UX were all new to me then) , and Octopress delivers on its promise to make it easy: just clone, bundle, and blog. Part of what makes Octopress so awesome is the deploy strategy: static pages are generated from yaml and markdown sources (saved in the source branch), and the pages are checked in to your github or heroku repository (as the master branch).&lt;/p&gt;
&lt;p&gt;When you clone the repo, you get both branches, but you have to do a little setup to ensure that master is pulling from and pushing to the right place. Borrowing some code from the &lt;a href=&quot;https://github.com/imathis/octopress/blob/master/Rakefile#L351-L358&quot;&gt;setup rake task&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; clone git@github.com:username/username.github.com.git my_blog
$ &lt;span class=&quot;token builtin class-name&quot;&gt;cd&lt;/span&gt; my_blog
$ &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; checkout &lt;span class=&quot;token builtin class-name&quot;&gt;source&lt;/span&gt;
$ &lt;span class=&quot;token function&quot;&gt;mkdir&lt;/span&gt; _deploy
$ &lt;span class=&quot;token builtin class-name&quot;&gt;cd&lt;/span&gt; _deploy
$ &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; init
$ &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; remote &lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt; origin git@github.com:username/username.github.com.git
$ &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; pull origin master
$ &lt;span class=&quot;token builtin class-name&quot;&gt;cd&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;
$ bundle &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt;
$ bundle &lt;span class=&quot;token builtin class-name&quot;&gt;exec&lt;/span&gt; rake preview&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now I have no excuses to not blog more often… well, fewer excuses (thanks to &lt;a href=&quot;http://code.dblock.org/octopress-setting-up-a-blog-and-contributing-to-an-existing-one&quot;&gt;Daniel Doubrovkine&lt;/a&gt; for pointing me in the right direction).&lt;/p&gt;
&lt;p&gt;I briefly considered switching to a hosted blogging platform (tumblr or wordpress), so I conducted an informal survey (sample size taken from &lt;a href=&quot;https://www.digitalocean.com/company/blog/20-developers-to-follow-in-2014/&quot;&gt;Digital Ocean’s 20 developers to follow&lt;/a&gt;) to see what choices leading developers were making, and it looks like a jekyll based blog is still the most popular. What is yours?&lt;/p&gt;
&lt;style type=&quot;text/css&quot;&gt;
.tg  {border-collapse:collapse;border-spacing:0;}
.tg td{font-family:Arial, sans-serif;font-size:14px;padding:10px 5px;border-style:solid;border-width:1px;overflow:hidden;word-break:normal;}
.tg th{font-family:Arial, sans-serif;font-size:14px;font-weight:normal;padding:10px 5px;border-style:solid;border-width:1px;overflow:hidden;word-break:normal;}
.tg .tg-s6z2{text-align:center}
&lt;/style&gt;
&lt;table class=&quot;tg&quot;&gt;
  &lt;tr&gt;
    &lt;th class=&quot;tg-031e&quot;&gt;platform&lt;/th&gt;
    &lt;th class=&quot;tg-031e&quot;&gt;users&lt;/th&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td class=&quot;tg-s6z2&quot;&gt;jekyll&lt;/td&gt;
    &lt;td class=&quot;tg-031e&quot;&gt;6&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td class=&quot;tg-031e&quot;&gt;octopress&lt;/td&gt;
    &lt;td class=&quot;tg-031e&quot;&gt;3&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td class=&quot;tg-031e&quot;&gt;none&lt;/td&gt;
    &lt;td class=&quot;tg-031e&quot;&gt;3&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td class=&quot;tg-031e&quot;&gt;tumblr&lt;/td&gt;
    &lt;td class=&quot;tg-031e&quot;&gt;1&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td class=&quot;tg-031e&quot;&gt;hand-rolled&lt;/td&gt;
    &lt;td class=&quot;tg-031e&quot;&gt;6&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td class=&quot;tg-031e&quot;&gt;wordpress&lt;/td&gt;
    &lt;td class=&quot;tg-031e&quot;&gt;1&lt;/td&gt;
  &lt;/tr&gt;
&lt;/table&gt;</content:encoded></item><item><title><![CDATA[the happiness hypothesis]]></title><description><![CDATA[“Nothing is miserable unless you think it so; and on the other hand, nothing brings happiness unless you are content with it.” —Buddha In…]]></description><link>http://katieleonard.ca/blog/2015/2015-01-01-the-happiness-hypothesis/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2015/2015-01-01-the-happiness-hypothesis/</guid><pubDate>Thu, 01 Jan 2015 00:00:00 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;“Nothing is miserable unless you think it so; and on the other hand, nothing brings happiness unless you are content with it.” —Buddha&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;In &lt;a href=&quot;http://www.amazon.com/Happiness-Hypothesis-Finding-Modern-Ancient/dp/0465028020/ref=sr_1_1?ie=UTF8&amp;#x26;qid=1420146441&amp;#x26;sr=8-1&amp;#x26;keywords=the+happiness+hypothesis&quot;&gt;The Happiness Hypothesis&lt;/a&gt;: Finding Modern Truth in Ancient Wisdom, Jonathan Haidt provides an extensive overview of the state of positive psychology today.&lt;/p&gt;
&lt;!--more--&gt;
&lt;p&gt;He uses the analogy of a rider on an elephant to describe how the mind is divided into two parts: the conscious, reasoning part (the rider), and the unconscious mind that is actually driving our behaviour (the elephant). Stepping in to the New Year, the twitter-verse is alive with resolutions to eat less, exercise more, and spend less money — all laudable goals for the rider, but unless you can re-train the elephant to want those same things, you will find yourself in line for a 16oz hot chocolate with whipped cream by the end of the week.&lt;/p&gt;
&lt;h3&gt;On the happiness equation: H = S + C + V&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;The level of happiness that you actually experience (H) is determined by your biological set point (S) plus the conditions of your life (C) plus the voluntary activities (V) you do.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This has certainly been true in my life. I tend towards a positive outlook (as Haidt describes it, a winner of the ‘cortical lottery’), but that doesn’t mean I don’t experience ups and downs brought on by circumstances and choices. Changing your level of happiness can come from changing your circumstances, or by participating in rewarding acitivites. (Out of ideas? Try &lt;a href=&quot;http://www.bodyvox.com/classes/beginning-ballet-and-wine-tasting-0&quot;&gt;beginning ballet and wine tasting&lt;/a&gt;!)&lt;/p&gt;
&lt;h3&gt;On training the elephant&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;“The goal of meditation is to change automatic thought processes, thereby taming the elephant. And the proof of taming is the breaking of attachments… For Buddha, attachments are like a game of roulette in which someone else spins the wheel and the game is rigged: The more you play, the more you lose. The only way to win is to step away from the table. And the only way to step away, to make yourself not react to the ups and downs of life, is to meditate and tame the mind. Although you give up the pleasures of winning, you also give up the larger pains of losing.”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I like the idea of training the elephant through meditation, but disagree with the pursuit of non-attachment. Living life without any attachments means missing out on joy as well as pain. If life is an amuzement park, is it better to spend your time on the teacups or the rollercoaster? Isn’t it better to have loved and lost than never to have loved at all?&lt;/p&gt;
&lt;h3&gt;On your inner lawyer&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;[People] are skilled at finding reasons to support their gut feelings. The rider acts like a lawyer whom the elephant has hired to represent it in the court of public opinion… Studies of everyday reasoning show that… when people are given difficult questions to think about… they generally lean one way or the other right away, and then put a call in to reasoning to see whether support for that position is forthcoming.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I love the idea of our conscious mind acting as a lawyer defending our actions and decisions. We only look for supporting evidence, and any data that undermines our world-view must be discredited or its importance downplayed.&lt;/p&gt;
&lt;h3&gt;On reciprocation and gossip&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;A species equipped with vengeance and gratitude responses can support larger and more cooperative social groups because the payoff to cheaters is reduced by the costs they bear in making enemies… Tit for tat appears to be built into human nature as a set of moral emotions that make us want to return favor for favor, insult for insult…&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Social groups cannot be formed without cooperation and a set of norms. Norms can be enforced through gossip:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Many species reciprocate, but only humans gossip, and much of what we gossip about is the value of other people as partners for reciprocal relationships… Gossip paired with reciprocity allow karma to work here on earth, not in the next life.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;On writing your life story&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;The third level of personality is that of the “life story.” Human beings in every culture are fascinated by stories; we create them wherever we can.. It’s no different with our own lives. We can’t stop ourselves from creating what McAdams describes as an “evolving story that integrates a reconstructed past, perceived present, and anticipated future into a coherent and vitalizing life myth.” Although the lowest level of personality is mostly about the elephant, the life story is written primarily by the rider. You create your story in consciousness as you interpret your own behavior, and as you listen to other people’s thoughts about you.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Every time I relate a personal anecdote to a new listener I find that I am refining the narrative — using the same words and phrases, pausing at the same moments each time. My partner and I have developed a cadence when we tell people about our drive across Canada, or our trip to the Maritimes. We are building our life story through relatable moments.&lt;/p&gt;
&lt;h3&gt;On growing through adversity&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;Be sure you have done your best to answer these two questions: Why did this happen? What good might I derive from it?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Whatever doesn’t kill you doesn’t always make you stronger, but we can grow through adversity. Pain doesn’t always equal gain, but a root cause analysis (why did this happen?), and reframing to find something positive in the experience (lessons learned), is a great approach.&lt;/p&gt;
&lt;h3&gt;On the ideological differences in moral ethics:&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;The ethic of autonomy, the ethic of community, and the ethic of divinity.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Policial and ideological differences arise from approaching life from different moral perspectives. In the ethic of autonomy, the goal is to protect individuals from harm and interference. In the ethic of community the goal is to protect the integrity of groups, families, companies, or nations, and its virtues are obedience, and loyalty. In the ethic of divinity, the goal is to protect the sacred from the profane. They value living in a pure and holy way, free from pollutants such as lust, greed, and hatred.&lt;/p&gt;
&lt;h3&gt;Vital engagement (or flow)&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;Vital engagement does not reside in the person or in the environment; it exists in the relationship between the two.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Memories that encorporate more than one sensation are the strongest. Similarly, finding meaning and flow in an activity requires more than just a connection through commitment. There must be connections through a community, a shared history, and a shared experience. I didn’t come to love programming because it seemed like a rewarding career path. I built a script that was useful to a coworker, drew excitment from other programmers, and began peeling back the layers of abstraction, enjoying the ‘A-ha!’ when understanding occurred.&lt;/p&gt;
&lt;h3&gt;On happiness and the meaning of life&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;Happiness is not something that you can find, acquire, or achieve directly. You have to get the conidtions right and then wait.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This is the first book I have read that really tried to approach the meaning of life, and my inner elephant has decided that Haidt is on the right track.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[method lookup in ruby]]></title><description><![CDATA[I have once more been working my way through Sandi Metz’ Practical Object-oriented Design in Ruby (POODR) for a few weeks, and developed a…]]></description><link>http://katieleonard.ca/blog/2014/2014-12-28-method-lookup-in-ruby/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2014/2014-12-28-method-lookup-in-ruby/</guid><pubDate>Sun, 28 Dec 2014 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I have once more been working my way through Sandi Metz’ &lt;a href=&quot;http://www.amazon.com/Practical-Object-Oriented-Design-Ruby-Addison-Wesley/dp/0321721330&quot;&gt;Practical Object-oriented Design in Ruby&lt;/a&gt; (POODR) for a few weeks, and developed a mental block about method lookup.&lt;/p&gt;
&lt;p&gt;In Chapter 6 (Acquiring behaviour through inheritance), she describes how to extract a superclass from a group of related classes that share some behaviour by pulling methods up the inheritance chain instead of driving specializations down. This approach ensures a clean abstraction, leaving no specialized behaviour in the superclass. Where I got stuck was in the call chain that enforces the common interface:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ruby&quot;&gt;&lt;pre class=&quot;language-ruby&quot;&gt;&lt;code class=&quot;language-ruby&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Foo&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token method-definition&quot;&gt;&lt;span class=&quot;token function&quot;&gt;initialize&lt;/span&gt;&lt;/span&gt;
    baz
  &lt;span class=&quot;token keyword&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token method-definition&quot;&gt;&lt;span class=&quot;token function&quot;&gt;baz&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;raise&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;NotImplementedError&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;You can&apos;t call #baz here!&quot;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Bar&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; Foo
  &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token method-definition&quot;&gt;&lt;span class=&quot;token function&quot;&gt;initialize&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;super&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token method-definition&quot;&gt;&lt;span class=&quot;token function&quot;&gt;baz&lt;/span&gt;&lt;/span&gt;
    puts &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Hello, baz&quot;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; x &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Bar&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt;
&lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Hello, baz&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;#&amp;lt;Bar:0x007fc4f903ab90&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I could not understand why, the &lt;code class=&quot;language-text&quot;&gt;NotImplementedError&lt;/code&gt; wasn’t raised when a new &lt;code class=&quot;language-text&quot;&gt;Bar&lt;/code&gt; was created. This is how I imagined the call stack should work:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;Bar.new&lt;/code&gt; calls &lt;code class=&quot;language-text&quot;&gt;Bar#initialize&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;Bar&lt;/code&gt; calls &lt;code class=&quot;language-text&quot;&gt;super&lt;/code&gt; (&lt;code class=&quot;language-text&quot;&gt;Foo#initialize&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;Foo&lt;/code&gt; calls &lt;code class=&quot;language-text&quot;&gt;baz&lt;/code&gt; (&lt;code class=&quot;language-text&quot;&gt;Foo#baz&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;raises &lt;code class=&quot;language-text&quot;&gt;NotImplementedError&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This is how the call stack actually works&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;x = Bar.new&lt;/code&gt; calls &lt;code class=&quot;language-text&quot;&gt;Bar#initialize&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;x&lt;/code&gt; receives a call to &lt;code class=&quot;language-text&quot;&gt;super&lt;/code&gt; (&lt;code class=&quot;language-text&quot;&gt;Foo#initalize&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;x&lt;/code&gt; receives a call to &lt;code class=&quot;language-text&quot;&gt;baz&lt;/code&gt; (&lt;code class=&quot;language-text&quot;&gt;Bar#baz&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;says “Hello, baz”&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The call never comes from the context of &lt;code class=&quot;language-text&quot;&gt;Foo&lt;/code&gt; — the receiver is always &lt;code class=&quot;language-text&quot;&gt;x&lt;/code&gt;, the instance of &lt;code class=&quot;language-text&quot;&gt;Bar&lt;/code&gt;. Classical inheritance dictates that an object can only look to itself or further up the inheritance chain for valid method definitions, not down. &lt;code class=&quot;language-text&quot;&gt;x&lt;/code&gt; is reaching up to call &lt;code class=&quot;language-text&quot;&gt;super&lt;/code&gt; but checks itself for an answer to the question &lt;code class=&quot;language-text&quot;&gt;#baz&lt;/code&gt;. &lt;code class=&quot;language-text&quot;&gt;Foo#baz&lt;/code&gt; would only ever be called if we made a new &lt;code class=&quot;language-text&quot;&gt;Foo&lt;/code&gt; directly:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;&gt; y = Foo.new
NotImplementedError: You can&apos;t call #baz here!
        from (irb):7:in `baz&apos;
        from (irb):3:in `initialize&apos;
        from (irb):27:in `new&apos;
        from (irb):27
        from /usr/local/var/rbenv/versions/2.1.5/bin/irb:11:in `&amp;lt;main&gt;&apos;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;How ruby resolves a message (classical inheritance)&lt;/h3&gt;
&lt;p&gt;The search for a method begins in the class of the receiving object — in the example above, Bar is always the receiving object. If the class does not implement the message, the search proceeds up the superclass chain. If none of the superclasses contain the method definition, ruby makes a second attempt to resolve the message by sending &lt;code class=&quot;language-text&quot;&gt;method_missing(:method_name)&lt;/code&gt; to the original object. The search restarts from the bottom, but this time for a &lt;code class=&quot;language-text&quot;&gt;method_missing&lt;/code&gt; handler rather than &lt;code class=&quot;language-text&quot;&gt;:method_name&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Occasionally refreshing the ruby basics is super-rewarding.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[compilers -- an intro]]></title><description><![CDATA[Last year, I was wrapping up a stint at code school, and I picked up the challenge of building a programming language. It was a very large…]]></description><link>http://katieleonard.ca/blog/2014/2014-11-08-compilers-an-intro/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2014/2014-11-08-compilers-an-intro/</guid><pubDate>Sat, 08 Nov 2014 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Last year, I was wrapping up a stint at code school, and I picked up the challenge of &lt;a href=&quot;http://katieleonard.ca/blog/2013/canadian-flair/&quot;&gt;building a programming language&lt;/a&gt;. It was a very large stretch-goal, and I didn’t complete the project, but I learned a lot about how languages are designed and built. Recently, my mentor highlighted a &lt;a href=&quot;http://online.stanford.edu/course/compilers-0&quot;&gt;Compilers course offered through Stanford Online&lt;/a&gt;, and suggested that it may be time to level-up my understanding of languages once again. Since I did not reach the compiler phase for &lt;code class=&quot;language-text&quot;&gt;eh?&lt;/code&gt;, perhaps this is an opportunity to do so.&lt;/p&gt;
&lt;h3&gt;Review of compilers&lt;/h3&gt;
&lt;p&gt;A compiler is different from an interpreter. An interpreter takes both the data and the program and produces output. A compiler takes only the program and produces an executable. Fun fact: I learned just recently that javascript is actually a “compiled” language — the javascript engine uses just-in-time compilation as it is executed.&lt;/p&gt;
&lt;p&gt;The grandfather of all compiled languages was FORTRAN, which was developed to translate formulas into a machine-readable language. Like many software projects, the initial completion date was wildly optimistic — it took 7 years longer than their original estimate — but they developed a 5-stage pattern of processing that all later compilers would follow.&lt;/p&gt;
&lt;h3&gt;1. Lexical analysis&lt;/h3&gt;
&lt;p&gt;This first step is about word and symbol recognition: breaking a stream of characters into recognizable chunks. For example a method definition:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;# Ruby
def my_method; end

// Java
public static void main() { }

# eh
can curl; eh?&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Recognizing white space, punctuation, and words is the first step in translating characters into actions that can be performed. The words that are recognized are usually converted into “tokens”, for passing in to the next stage of processing, which is why this step is occasionally called Tokenizing.&lt;/p&gt;
&lt;h3&gt;2. Parsing&lt;/h3&gt;
&lt;p&gt;After the character stream has been tokenized, doing pattern recognition on the sequence of tokens is called parsing. Returning briefly to the example of a method definition, &lt;code class=&quot;language-text&quot;&gt;def my_method; end&lt;/code&gt;, the lexer would recognize &lt;code class=&quot;language-text&quot;&gt;def&lt;/code&gt; as a key word and &lt;code class=&quot;language-text&quot;&gt;my_method&lt;/code&gt; as a variable, but they are grouped together by the parser as the beginning of a method block.&lt;/p&gt;
&lt;h3&gt;3. Semantic analysis&lt;/h3&gt;
&lt;p&gt;Compilers can only do a very limited amount of semantic analysis, usually limited to catching inconsistencies (such as redeclaring a variable) and ambiguities (such as type mismatches). “A panda bear walks into a bar and eats, shoots and leaves”, can be tokenized into component parts (verbs, nouns, articles), as well as into phrases (subject, predicate), but determining the exact meaning of the predicate requires deeper understanding of the subject. Machines do not perform well with ambiguous grammar, and developing an unambiguous language syntax is a difficult task.&lt;/p&gt;
&lt;h3&gt;4. Optimization&lt;/h3&gt;
&lt;p&gt;Optimization is where most modern language compilers spend the majority of their resources, modifying programs so that they reduce the demand for resources like memory allocation, or garbage collection. For example, the java compiler will “unroll” all the for loops so that they run more efficiently. Another strategy is &lt;a href=&quot;http://en.wikipedia.org/wiki/Optimizing_compiler&quot;&gt;peephole&lt;/a&gt; optimization, where the compiler checks out adjacent code to see if any assignments could be reduced or replaced by simple math.&lt;/p&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;x = y * 2&lt;/code&gt; might be reduced to &lt;code class=&quot;language-text&quot;&gt;x = y + y&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;z = 0; x = y * z&lt;/code&gt; might be reduced to &lt;code class=&quot;language-text&quot;&gt;x = 0&lt;/code&gt;, but there is a gotcha hidden there — &lt;code class=&quot;language-text&quot;&gt;y * 0 = 0&lt;/code&gt; is only true for integers. It results in &lt;code class=&quot;language-text&quot;&gt;NaN&lt;/code&gt; for floating point numbers.&lt;/p&gt;
&lt;h3&gt;5. Code generation&lt;/h3&gt;
&lt;p&gt;Code generation is the final translation of the program into an executable. The written language has been cut into tokens and parsed into phrases. It has been examined for ambiguities and inconsistencies, and optimized wherever possible. The instructions for the program are arranged neatly and must now be evaluated and scheduled. The final product is an executable program that can be run against any data of interest.&lt;/p&gt;
&lt;p&gt;This 5 stage pattern is followed by almost all compilers. Where they vary is in their proportions. FORTRAN spent a balanced amount of time in each of the 5 phases, while modern compilers have a much longer optimization phase than lexing or parsing.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[how to solve it]]></title><description><![CDATA[4 phases: Understand the problem - see clearly what is required Find connections and make a plan Carry out the plan Look back at the…]]></description><link>http://katieleonard.ca/blog/2014/2014-11-06-how-to-solve-it/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2014/2014-11-06-how-to-solve-it/</guid><pubDate>Thu, 06 Nov 2014 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;4 phases:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Understand the problem - see clearly what is required&lt;/li&gt;
&lt;li&gt;Find connections and make a plan&lt;/li&gt;
&lt;li&gt;Carry out the plan&lt;/li&gt;
&lt;li&gt;Look back at the completed solution - review and discuss&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;“To devise a plan, to conceive of the idea of a solution is not easy. It takes so much to succeed: formerly acquired knowledge, good mental habits, concentration on the purpose, and one more thing: good luck. To carry out the plan is much easier; what we need is mainly patience.”&lt;/p&gt;
&lt;p&gt;“…by reconsidering and examining the result and the path that led to it, they could consolidate their knowledge and develop their ability to solve problems.”&lt;/p&gt;
&lt;p&gt;“There remains always something to do; with sufficient study and penetration, we could improve any solution, and, in any case, we can always improve our understanding of the solution.”&lt;/p&gt;
&lt;h1&gt;Where do I start?&lt;/h1&gt;
&lt;p&gt;Start with the problem statement&lt;/p&gt;
&lt;h1&gt;What can I do?&lt;/h1&gt;
&lt;p&gt;Isolate the principle parts of the problem&lt;/p&gt;
&lt;p&gt;A problem to prove has a hypothesis and a conclusion
A problem to find has data, conditions, and an unknown&lt;/p&gt;
&lt;p&gt;If a problem is very complex, you may distinguish great and small steps. Consider the great ones first and get down to the smaller ones after.&lt;/p&gt;
&lt;h1&gt;Looking back&lt;/h1&gt;
&lt;p&gt;start with the solution
consider the solution from various sides
scrutinize the method that led you to the solution&lt;/p&gt;</content:encoded></item><item><title><![CDATA[meteor-managed ids won't play nicely with others]]></title><description><![CDATA[I am working with a data dump from a meteor project, and while retrieving and displaying the existing collection was no problem at all, I…]]></description><link>http://katieleonard.ca/blog/2014/2014-10-18-make-meteor-minimongo-ids-play-nice/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2014/2014-10-18-make-meteor-minimongo-ids-play-nice/</guid><pubDate>Sat, 18 Oct 2014 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I am working with a data dump from a meteor project, and while retrieving and displaying the existing collection was no problem at all, I was stuck on saving new documents to mongo.&lt;/p&gt;
&lt;p&gt;My schema was pretty straightforward and taken directly from an existing document:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;var postSchema = mongoose.Schema({
  &quot;title&quot; : String,
  &quot;company&quot; : String,
  &quot;author&quot; : String,
  &quot;music&quot; : String,
  &quot;choreographer&quot; : String,
  &quot;showDate&quot; : String,
  &quot;image&quot;: String,
  &quot;userId&quot; : String,
  &quot;postAuthor&quot; : String,
  &quot;submitted&quot; : Number,
  &quot;commentsCount&quot; : Number,
  &quot;_id&quot;:  String
});&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The problem was that last field: &lt;code class=&quot;language-text&quot;&gt;_id&lt;/code&gt;. If I included it in the schema then I would have the objectId available on the front end but would get an error trying to insert a new document: &lt;code class=&quot;language-text&quot;&gt;[Error: document must have an _id before saving]&lt;/code&gt;. If I removed &lt;code class=&quot;language-text&quot;&gt;_id&lt;/code&gt; from the schema I could save documents just fine but could not pass through the objectIds of already existing documents. I have learned that mongo is very flexible when it comes to assigning ids before insertion into the database.&lt;/p&gt;
&lt;p&gt;Mongo objects created through a meteor application are given meteor-friendly objectIds, the uniqueness of which is monitored and maintained by a meteor wrapper class. The design decision to go with ids as strings seems to be &lt;a href=&quot;https://groups.google.com/forum/#!topic/meteor-talk/f-ljBdZOwPk&quot;&gt;motivated by meteor’s latency compensation feature&lt;/a&gt; — creating documents on the client-side and then later syncing them with the server requires that they are assigned objectIds before they ever reach mongo. Mongo will accept a manually entered id, trusting that there is an entity somewhere that is managing uniqueness.&lt;/p&gt;
&lt;p&gt;Here was my problem: the documents created by meteor had String ids assigned by meteor. If I included &lt;code class=&quot;language-text&quot;&gt;_id&lt;/code&gt; in my schema, mongo would assume that I was managing id assignment manually, and wouldn’t save the object until I did. If I did not include &lt;code class=&quot;language-text&quot;&gt;_id&lt;/code&gt; in my schema, mongo would assume it was responsible, and would assign a unique id accordingly.&lt;/p&gt;
&lt;p&gt;To make the documents created by meteor play nice with the new stack, I had to update each document’s &lt;code class=&quot;language-text&quot;&gt;_id&lt;/code&gt; with one created by mongo. Unfortunately, mongo won’t allow modification of &lt;code class=&quot;language-text&quot;&gt;_id&lt;/code&gt; directly, so the only choice was to recreate and insert each entry, then delete the original:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Retrieve a document: &lt;code class=&quot;language-text&quot;&gt;doc = db.posts.findOne()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Save the title: &lt;code class=&quot;language-text&quot;&gt;title = doc.title&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Save the document’s string id: &lt;code class=&quot;language-text&quot;&gt;id = doc._id&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Reassign the document id: &lt;code class=&quot;language-text&quot;&gt;doc._id = ObjectId()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Save the updated document: &lt;code class=&quot;language-text&quot;&gt;db.posts.insert(doc)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Remove the original document: &lt;code class=&quot;language-text&quot;&gt;db.posts.remove({_id: id})&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Verify that the post exists with the new id: &lt;code class=&quot;language-text&quot;&gt;db.posts.findOne({&quot;title&quot;: title})&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;&gt; doc = db.posts.findOne()
{
  &quot;title&quot; : &quot;La Cage aux Folles&quot;,
  &quot;company&quot; : &quot;Pixie Dust Productions&quot;,
  &quot;author&quot; : &quot;Harvey Fierstein&quot;,
  &quot;music&quot; : &quot;Jerry Herman&quot;,
  &quot;showDate&quot; : ISODate(&quot;2014-09-21T07:00:00Z&quot;),
  &quot;dateSubmitted&quot; : 1411346259065,
  &quot;_id&quot; : &quot;EjzopWQa3mw5LB979&quot;
}

&gt; title = doc.title
La Cage aux Folles

&gt; id = doc._id
EjzopWQa3mw5LB979

&gt; doc._id = ObjectId()
ObjectId(&quot;5442af27cc37fe6f03648fdd&quot;)

&gt; db.posts.insert(doc)

&gt; db.posts.remove({_id: id})

&gt; db.posts.findOne({&quot;title&quot;: title})
{
  &quot;_id&quot; : ObjectId(&quot;5442af27cc37fe6f03648fdd&quot;),
  &quot;title&quot; : &quot;La Cage aux Folles&quot;,
  &quot;company&quot; : &quot;Pixie Dust Productions&quot;,
  &quot;author&quot; : &quot;Harvey Fierstein&quot;,
  &quot;music&quot; : &quot;Jerry Herman&quot;,
  &quot;showDate&quot; : ISODate(&quot;2014-09-21T07:00:00Z&quot;),
  &quot;dateSubmitted&quot; : 1411346259065,
  &quot;commentsCount&quot; : 1
}
&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Here is a handy script for changing the entire collection at once:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;db.posts.find().forEach(function(doc){ var doc = db.posts.findOne(); var title = doc.title; var id = doc._id; doc._id = ObjectId(); db.posts.insert(doc); db.posts.remove({_id: id}); })&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Awesome.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Sort all the things with mongo and node.js]]></title><description><![CDATA[Sorting shouldn’t be difficult, but through my experience learning meteor I discovered that if mongo likes sort commands one way:  meteor…]]></description><link>http://katieleonard.ca/blog/2014/2014-10-09-sort_things_with_mongoose/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2014/2014-10-09-sort_things_with_mongoose/</guid><pubDate>Thu, 09 Oct 2014 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Sorting shouldn’t be difficult, but through my experience learning meteor I discovered that if mongo likes sort commands one way:&lt;/p&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;db.posts.find().sort({submitted: -1})&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;meteor would like them a different way:&lt;/p&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;Posts.find({}, {sort: {submitted : -1}}&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;I am adapting one of my meteor projects to use mongo and node.js, connected through mongoose, and fitting in the callback required for node sent me to the google. After a few stackoverflow searches I turned up a several options:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;Post.find({}, {sort:[[&apos;submitted&apos;,-1]]}, function(err, doc) {
  response.send(doc);
});&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This option returned a object containing only the entry ids, not the full documents:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;0: {_id:2tcte4Srd8QMSqrKt}
1: {_id:5c3FdWphiYiMQzukw}
2: {_id:62vAt5ewucKm542DH}
3: {_id:AWNYsxBgFnv9Z4NSA}
...&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Another option suggested that converting the result to an Array would complete the query:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;Post.find({},{sort: [[&apos;submitted&apos;,-1]]}).toArray(function(e, results){
  response.send(results);
});&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This option resulted in &lt;code class=&quot;language-text&quot;&gt;TypeError: Object #&amp;lt;Query&gt; has no method &apos;toArray&apos;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Rather than continuing to search for a snippet to steal, I turned to the source, and it turns out that querying mongo from mongoose is simpler than either of these strategies.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;Post.find()
  .sort(&quot;-submitted&quot;)
  .exec(function(err, doc) {
    response.send(doc);
  });&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Success! Why? Because while mongo itself returns a cursor object which can be transformed into documents using &lt;code class=&quot;language-text&quot;&gt;toArray()&lt;/code&gt;, or &lt;code class=&quot;language-text&quot;&gt;fetch()&lt;/code&gt; in the case of meteor, mongoose returns a &lt;a href=&quot;http://mongoosejs.com/docs/queries.html&quot;&gt;Query&lt;/a&gt; object, which will return the full documents once it is passed a callback.&lt;/p&gt;
&lt;p&gt;A Query object can be built using &lt;a href=&quot;https://github.com/LearnBoost/mongoose/blob/master/lib/query.js#L211-L216&quot;&gt;method chaining&lt;/a&gt; —
each method (find | where | limit | select | sort) returns a new Query object, which allows you to build in stages:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;Post
.find({ title: /the/ }) // query
.where(&apos;cost&apos;).gt(17).lt(66)  // query
.where(&apos;location&apos;).in([&apos;Schnitz&apos;, &apos;Armory&apos;])  // query
.limit(10)  // query
.sort(&apos;-ticketDate&apos;)  // query
.select(&apos;title company&apos;)  // query
.exec(callback);  // EXECUTE THE QUERY&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Another fun bit of javascript/mongoose magic, is that you can indicate &lt;a href=&quot;https://github.com/LearnBoost/mongoose/blob/master/lib/query.js#L1295-L1297&quot;&gt;sorting in descending order&lt;/a&gt; by prefacing the sort string with a ”-” :&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;Post
.find({ title: /the/ }) // query
.sort(&apos;-ticketDate&apos;)  // DESC!
.exec(callback);  // EXECUTE THE QUERY&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Awesome.&lt;/p&gt;
&lt;h3&gt;Resources&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;http://docs.mongodb.org/manual/reference/operator/meta/orderby/&quot;&gt;mongo docs&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://stackoverflow.com/a/20859457&quot;&gt;stackoverflow&lt;/a&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[giving the cold shoulder with git]]></title><description><![CDATA[Some files become unnecessary to track using version control, but still belong in the repository. Compiled assets, for example may require a…]]></description><link>http://katieleonard.ca/blog/2014/2014-09-08-giving-the-cold-shoulder-with-git/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2014/2014-09-08-giving-the-cold-shoulder-with-git/</guid><pubDate>Mon, 08 Sep 2014 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Some files become unnecessary to track using version control, but still belong in the repository. Compiled assets, for example may require a placeholder for a functional deploy, but don’t need to be checked in every time a change is made.&lt;/p&gt;
&lt;p&gt;Adding the file to your gitignore is not enough to stop tracking file changes. You must also clear the file from your git cache:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ git rm --cached [filename]
$ git add .
$ git commit -m &quot;I really mean to ignore this file.&quot;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;To untrack everything that has been added to the .gitignore:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ git rm -r --cached .
$ git commit -a -m &quot;I mean it!&quot;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;Resources&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;http://stackoverflow.com/a/1139797&quot;&gt;Here’s where I found this gem&lt;/a&gt;,
&lt;a href=&quot;http://git-scm.com/docs/gitignore&quot;&gt;and here are the docs where I verified it&lt;/a&gt;.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[gaining closure through modules]]></title><description><![CDATA[If you have more than one javascript running on a page, you have likely experienced the hell of trying to debug a problem caused by naming…]]></description><link>http://katieleonard.ca/blog/2014/2014-09-06-managing-modules/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2014/2014-09-06-managing-modules/</guid><pubDate>Sat, 06 Sep 2014 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;If you have more than one javascript running on a page, you have likely experienced the hell of trying to debug a problem caused by naming collisions. Developing the scripts in isolation, it makes sense to assign widgetA.name dynamically using jQuery, but then why does the title of widgetGraphB disappear? Avoid the pain of unintended consequences by namespacing your scripts. &lt;!--more--&gt;&lt;/p&gt;
&lt;p&gt;Closures occur when you pass functions to variables to call at a later date. The javascript engine does all the work of compiling the script and loading the contents into the memory stack, but until the function is called the stack just sits there, sealed like a time capsule.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;function timeCapsule() {
  var year = 1999;
  function party() {
    console.log(&quot;We&apos;re gonna party like it&apos;s &quot; + year);
  }

  return party;
}

var year = 2099;
var tonight = timeCapsule();

tonight(); // We&apos;re gonna party like it&apos;s 1999&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The &lt;code class=&quot;language-text&quot;&gt;party()&lt;/code&gt; function has a closure over &lt;code class=&quot;language-text&quot;&gt;timeCapsule()&lt;/code&gt;, which means all the variables and functions within timeCapsule remain unmolested by any assignments made outside of their scope.&lt;/p&gt;
&lt;h3&gt;Modules use closure to encapsulate scope.&lt;/h3&gt;
&lt;p&gt;Breaking your monolithic javascript into modules is a great way to separate concerns and create closures.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;function myModuleFunction() { /* Do work1 */ }
function mySecondModuleFuntion() { /* Do work2 */ }

exports.myModuleFunction = myModuleFunction;
exports.mySecondModuleFunction = mySecondModuleFunction;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;var myModule = require(&quot;myModule&quot;);

myModule.myModuleFunction(); // performs work1
myModule.mySecondModuleFunction(); // performs work2&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Using modules will prevent naming conflicts on functions and variables:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; module1 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;myModuleName&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token function&quot;&gt;myModuleFunction&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;All work and no play makes module1 a dull script;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

module1&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;myModuleFunction&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// performs work1&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;myModuleFunction&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// outputs snarky phrase&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Voila — no conflicts.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[backup meteor? yes we can]]></title><description><![CDATA[Retrieving a data dump from your meteor production database and copying it to local development is a three-step, time sensitive process.…]]></description><link>http://katieleonard.ca/blog/2014/2014-08-24-backup-meteor-yes-we-can/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2014/2014-08-24-backup-meteor-yes-we-can/</guid><pubDate>Sun, 24 Aug 2014 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Retrieving a data dump from your meteor production database and copying it to local development is a three-step, time sensitive process.&lt;/p&gt;
&lt;h3&gt;1. Retrieve your production url&lt;/h3&gt;
&lt;p&gt;Passing a &lt;code class=&quot;language-text&quot;&gt;-url&lt;/code&gt; flag to the &lt;code class=&quot;language-text&quot;&gt;meteor mongo&lt;/code&gt; command will return a long string of goodies:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ meteor mongo --url my_app.meteor.com

mongodb://client-12345678:9abcdef1-234-5678-9abc-def123456789@singularsensation-db-a3.meteor.io:12345/my_app_meteor_net&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This string contains all the information you require to access your production data:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;your client id (from // to :)&lt;/li&gt;
&lt;li&gt;a server password (from : to @)&lt;/li&gt;
&lt;li&gt;a server name and port number (from @ to /)&lt;/li&gt;
&lt;li&gt;the datastore identification (from / to the end)&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;mongodb://&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;CLIENT_ID&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;:&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;PASSWORD_HASH&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;@&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;SERVER_NAME:PORT&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;/&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;YOUR_DATA_STORE&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Retrieving your data is time-sensitive because the password hash will expire after 60 seconds.&lt;/p&gt;
&lt;h3&gt;2. Retrieve your data using mongodump&lt;/h3&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ mongodump -u CLIENT_ID -h SERVER_NAME:PORT -d YOUR_DATA_STORE -p PASSWORD_HASH

connected to: &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;SERVER_NAME:PORT&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
Sun Aug &lt;span class=&quot;token number&quot;&gt;24&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;:50:32.342 DATABASE: YOUR_DATA_STORE  to   dump/YOUR_DATA_STORE
Sun Aug &lt;span class=&quot;token number&quot;&gt;24&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;:50:32.989   YOUR_DATA_STORE.system.indexes to dump/YOUR_DATA_STORE/system.indexes.bson
Sun Aug &lt;span class=&quot;token number&quot;&gt;24&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;:50:34.368      &lt;span class=&quot;token number&quot;&gt;14&lt;/span&gt; objects
Sun Aug &lt;span class=&quot;token number&quot;&gt;24&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;:50:34.369   YOUR_DATA_STORE.system.users to dump/YOUR_DATA_STORE/system.users.bson
Sun Aug &lt;span class=&quot;token number&quot;&gt;24&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;:50:34.559      &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt; objects
&lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;. and on and on&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Mongodb copies your data from production into a new folder called “dump” in your present working directory.&lt;/p&gt;
&lt;h3&gt;3. Use mongorestore to copy the data from the dump into your local datastore&lt;/h3&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ mongorestore --host 127.0.0.1 --port 3001 --db meteor --drop dump/YOUR_DATA_STORE/

connected to: 127.0.0.1:3001
Sun Aug 24 11:36:54.693 dump/YOUR_DATA_STORE/users.bson
Sun Aug 24 11:36:54.693   going into namespace [meteor.users]
Sun Aug 24 11:36:54.693    dropping
2 objects found
Sun Aug 24 11:36:55.834   Creating index: { name: &quot;_id_&quot;, key: { _id: 1 }, ns: &quot;meteor.users&quot; }
Sun Aug 24 11:36:55.993   Creating index: { name: &quot;username_1&quot;, key: { username: 1 }, unique: true, ns: &quot;meteor.users&quot;, sparse: 1 }
... and on and on&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Awesome.&lt;/p&gt;
&lt;p&gt;Resources:
&lt;a href=&quot;http://stackoverflow.com/a/12447710&quot;&gt;stackoverflow&lt;/a&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[formatting numbers the easy way]]></title><description><![CDATA[D3 has an awesome number formatting function that I discovered only after hacking my own. My first approach was to use string and array…]]></description><link>http://katieleonard.ca/blog/2014/2014-08-23-formatting-numbers-the-easy-way/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2014/2014-08-23-formatting-numbers-the-easy-way/</guid><pubDate>Sat, 23 Aug 2014 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;D3 has an awesome number formatting function that I discovered only after hacking my own. My first approach was to use string and array manipulation to convert 1234567890 to 1,234,567,890:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;numberSmoothing&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// split the number into a character array and reverse it&lt;/span&gt;
  reversedNumber &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;value&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;reverse&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// [&quot;0&quot;, &quot;9&quot;, &quot;8&quot;, &quot;7&quot;, &quot;6&quot;, &quot;5&quot;, &quot;4&quot;, &quot;3&quot;, &quot;2&quot;, &quot;1&quot;]&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// push the numbers onto another array in groups of 3 and add a comma&lt;/span&gt;
  chunkedNumber &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;reversedNumber&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; numberChunk &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; reversedNumber&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;splice&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    chunkedNumber&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;push&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;reversedNumber&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;,&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    reversedNumber &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; numberChunk&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// push the remaining digits onto the array&lt;/span&gt;
  chunkedNumber&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;push&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;reversedNumber&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// [&quot;098,&quot;, &quot;765,&quot;, &quot;432,&quot;, &quot;1&quot;]&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// reverse each of the strings in the array and rejoin them&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; j &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; j &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; chunkedNumber&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; j&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    chunkedNumber&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;j&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; chunkedNumber&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;j&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;reverse&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// [&quot;,890&quot;, &quot;,567&quot;, &quot;,234&quot;, &quot;1&quot;]&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; chunkedNumber&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;reverse&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;numberSmoothing&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1234567890&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token string&quot;&gt;&quot;1,234,567,890&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;While it was a fun mental exercise to implement number formatting, I stumbled across this handy d3 function after I was already done:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;&gt; var format = d3.format(&quot;,&quot;);
&gt; format(1234567890);
&quot;1,234,567,890&quot;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;As it turns out, any way one might want to format a number has &lt;a href=&quot;https://github.com/mbostock/d3/wiki/Formatting#d3_format&quot;&gt;already been implemented in d3&lt;/a&gt;. It is similar to the mini-formatting language from python:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;[​[fill]align][sign][symbol][0][width][,][.precision][type]&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// add commas for the thousands separator&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; format &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; d3&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;,&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1234567890&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token string&quot;&gt;&quot;1,234,567,890&quot;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// add a sign for positive and negative numbers&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; format &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; d3&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;+,&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1234567890&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token string&quot;&gt;&quot;+1,234,567,890&quot;&lt;/span&gt;

&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1234567890&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token string&quot;&gt;&quot;-1,234,567,890&quot;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// add a currency sign&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; format &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; d3&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;+$,&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1234567890&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token string&quot;&gt;&quot;+$1,234,567,890&quot;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// as a percentage&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; format &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; d3&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;p&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token string&quot;&gt;&quot;16.666666666666664%&quot;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// as a rounded percentage&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; format &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; d3&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;%&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token string&quot;&gt;&quot;17%&quot;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// as a percent rounded to a single sig fig&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; format &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; d3&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;.1%&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token string&quot;&gt;&quot;16.7%&quot;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// as a rounded value&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; format &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; d3&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;.2r&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;123.456&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token string&quot;&gt;&quot;120&quot;&lt;/span&gt;

&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;123456789.66&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token string&quot;&gt;&quot;120000000&quot;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// as a rounded, comma separated value&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; format &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; d3&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;,.2r&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;123456789.66&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token string&quot;&gt;&quot;120,000,000&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Awesome.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[javascript getters and setters]]></title><description><![CDATA[Getters and setters make sense in java, and I just learned that there is an equivalent pattern in javascript: The  and  key words are…]]></description><link>http://katieleonard.ca/blog/2014/2014-08-09-javascript-getters-and-setters/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2014/2014-08-09-javascript-getters-and-setters/</guid><pubDate>Sat, 09 Aug 2014 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Getters and setters make sense in java, and I just learned that there is an equivalent pattern in javascript:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; favouriteBook &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;_title&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Catch-22&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Getting title&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_title&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_title &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; value&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Setting title&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_title&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; favouriteBook&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;title
 Getting title Catch&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;22&lt;/span&gt;

&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; favouriteBook&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;title &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Slaughterhouse 5&quot;&lt;/span&gt;
 Setting title Slaughterhouse &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;

&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; favouriteBook&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;title
 Getting title Slaughterhouse &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The &lt;code class=&quot;language-text&quot;&gt;get&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;set&lt;/code&gt; key words are reserved for accessing or mutating a data property (instance variable). Of course, one can get and set data properties directly:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; favouriteBook&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;title
&lt;span class=&quot;token string&quot;&gt;&quot;Catch-22&quot;&lt;/span&gt;

&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; favouriteBook&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;title &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Slaughterhouse 5&quot;&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; favouriteBook&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;title
&lt;span class=&quot;token string&quot;&gt;&quot;Slaughterhouse 5&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The advantage of using a getter and setter is that if a setter is defined without a getter, one can change the value of the data property, but can never read it. If a getter is defined without a setter, then the variable can be read but not be changed:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; favouriteBook &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;_title&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Catch-22&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Getting title&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_title&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; favouriteBook&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;title
Getting title Catch&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;22&lt;/span&gt;

&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; favouriteBook&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;title &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Slaughterhouse 5&quot;&lt;/span&gt;

&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; favouriteBook&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;title
Getting title Catch&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;22&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The setter function will fail silently, which makes troubleshooting difficult but ensures that the property remains undisturbed.&lt;/p&gt;
&lt;h3&gt;Resources&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;http://www.amazon.com/Principles-Object-Oriented-JavaScript-Nicholas-Zakas/dp/1593275404/ref=sr_1_1?ie=UTF8&amp;#x26;qid=1407339036&amp;#x26;sr=8-1&amp;#x26;keywords=principles+of+object+oriented+javascript&quot;&gt;The principles of object-oriented javascript&lt;/a&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[constructors and prototypes]]></title><description><![CDATA[Object-oriented programming (OOP) can be thought of as describing the properties and behaviour of a noun in a blueprint, which is used to…]]></description><link>http://katieleonard.ca/blog/2014/2014-08-07-constructors-and-prototypes/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2014/2014-08-07-constructors-and-prototypes/</guid><pubDate>Thu, 07 Aug 2014 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Object-oriented programming (OOP) can be thought of as describing the properties and behaviour of a noun in a blueprint, which is used to create instances of an object. The blueprint is defined as a Constructor — a function that identifies a class of objects and begins with a capital letter. New objects are created by calling a Constructor with the keyword &lt;code class=&quot;language-text&quot;&gt;new&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;Book&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;title&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; author&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;title &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; title&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;author &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; author&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function-variable function&quot;&gt;listing&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;title&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;by&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;author&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos; &apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; book1 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Book&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Catch-22&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Joseph Heller&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; book1&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;title
&lt;span class=&quot;token string&quot;&gt;&quot;Catch-22&quot;&lt;/span&gt;

&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; book1&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;author
&lt;span class=&quot;token string&quot;&gt;&quot;Joseph Heller&quot;&lt;/span&gt;

&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; book1&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;listing&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
Catch&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;22&lt;/span&gt; by Joseph Heller&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The Book constructor specifies two properties, &lt;code class=&quot;language-text&quot;&gt;title&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;author&lt;/code&gt;, and one method, &lt;code class=&quot;language-text&quot;&gt;listing&lt;/code&gt;. Defining a method in a constructor ensures that all instances of the Object have the same method, but it also results in duplication of the method in the memory stack for every instance of the Object. If I made 1000 instances of Book, there would be 1000 instances of the listing method, even though it is only defined once, and is the same for every object.&lt;/p&gt;
&lt;h4&gt;Memory stack of objects with instance methods:&lt;/h4&gt;
&lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 250px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/d870a511581930e9988eb3791ebb54fc/63868/post_constructor_memory_stack.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 132.91139240506328%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAbCAIAAADzvTiPAAAACXBIWXMAAAsTAAALEwEAmpwYAAADjklEQVQ4y5WUiXKqSBSG8/6vkok1NXfcxoSlm00EmkUlqFEv7l4FWRo1CkwBkXhvpqZmviooqum/D5xz/vOAEOJ5nvsCe+Prq2K/ZVkPNE23Wq17PcuygiDIsixLsiwroihy/K/n1mq1TqfzACHsdrtpmiZJkqZpHMdpmg6HFoRA03SCJASWCU/nfENakCQJAECW5QcAwL24uM/sKUURPN+mKGr4al7yE0sKsSRJWWRFUTDGnnfwfT8IAs/zgiA4Ho9RFJ3P5yiKgp/xfZ8kySxyKcYhDoPAcZwoijDGfs5+t3McJzvR9718pRRnkQFkDFWGNPyz2nAPh9HAYhjYaLYkBVlm95mEvu+Vv/PrZwMAdQ2N38YAMr1+f27bg+FQ1TXDMEyzryL03V6MR6Pvk8nwbbJer67XOIljmqaLyFBDMlIRBViOZbqG/n5N+z2DYxmCoiFJDsfTNsu0GrWn36uWNbxer2mSfIghZFRZhIzw0mzxbXE4GetIgQCoGqIoCCEjyUocJ+UHF/dbZAC6hr7ZbOf2bDqdTqZT73CYz+zVZr1Yrhbz2WK1vsZxkiTZdRN/lsowjPtTy9yUKbr+zOVyoWn6o0mq1Wotp5pT+w9Uq9VM3Gg0KpXKb194vFGpVJ6enu5fVSqVx8dHjuMeeJ4HAKiqim4oiqLrumUNLMt6tax8QUF3KIpCEARCKHOVpmmFJZIkySqRpma/+1ezKQhio1EjKXK2WJUbsszF8a3D/skYi7nNMFDsSALPCULbD/B9k913GEBIfX9/zzsan8+nKMKn3INF7q/XS9HtGOPj8XQ6nTDGFEV9lEqWJNd1Dwfv4Lrz+XzvuDiKwjB09k4Q+K7rhiEOwxBjvNmsN9ut67oEQeSlyo3Bsdy3b7UgDHuGVm+2xDYPeK5WrQHihcnmitCRJEEU+2bPtmdpmpYdBg1NfRu9sSzX75vzmT0YDCmSgAxUVU2WRN3oqaoqtNu9Xq/bM/f7XfIpzowhKQjRDMexsGd0w+hk9k2l0x69TWx7CiCn6frLy3O9/gcvysfjKS5dVRqjVW+yfPt1NDBUFQIgyR2SBJAGHRkleeqKKhal+jRGr2s4jrterReLxWy5DPxgvVrt9vvtdvdjs9luf8R3k6Dg0xiyrFwul1PO8XjEUVQ8lCv3AywMQ8/zPmYYTdPNZvP5X3n5Qr1ez+b2eDy2/ieDwcA0zeVy+Te+nGDbEoccUwAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;post constructor memory stack&quot; title=&quot;post constructor memory stack&quot; src=&quot;/static/d870a511581930e9988eb3791ebb54fc/63868/post_constructor_memory_stack.png&quot; srcset=&quot;/static/d870a511581930e9988eb3791ebb54fc/c26ae/post_constructor_memory_stack.png 158w,
/static/d870a511581930e9988eb3791ebb54fc/63868/post_constructor_memory_stack.png 250w&quot; sizes=&quot;(max-width: 250px) 100vw, 250px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
&lt;p&gt;Enter Prototypes.&lt;/p&gt;
&lt;p&gt;A Prototype is a property that is shared by all instances of an object. When the constructor for an object is called for the first time, all the object’s properties are loaded onto the memory stack as well as the object’s Prototype. All subsequent instances of that object include a pointer to the same Prototype, and they pass in a pointer to themselves as &lt;code class=&quot;language-text&quot;&gt;this&lt;/code&gt; whenever they call a method from the Prototype.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;Book&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;title&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; author&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;title &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; title&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;author &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; author&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token class-name&quot;&gt;Book&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;prototype &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token function-variable function&quot;&gt;listing&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;title&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;by&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;author&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos; &apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; book1 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Book&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Catch-22&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Joseph Heller&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; book2 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Book&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Slaughterhouse 5&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Kurt Vonnegut&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; book1&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;listing&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
Catch&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;22&lt;/span&gt; by Joseph Heller
&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; book2&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;listing&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
Slaughterhouse &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt; by Kurt Vonnegut

&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; book1&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;hasOwnProperty&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;listing&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;listing&apos;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; book1
&lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h4&gt;Memory stack of object with prototypes:&lt;/h4&gt;
&lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 339px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/41636f46f9c6e624e43302ac64aa27ac/16caa/post_prototype_memory_stack.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 133.54430379746836%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAbCAIAAADzvTiPAAAACXBIWXMAAAsTAAALEwEAmpwYAAAEGUlEQVQ4y22U23KiQBBA/f+P2Iet3bck6mrUGAiXgQGBAeQmEsxNBaIoF6PGiM6WMUmlrJwHHqbmMN093VPSNI37BAAAIZTe6XQ63DcAAL7vY4z3+z3+pMQwjOu6cRxHURTHse/7iqIghGRFGY/Hk8nkuC7Lsq7rpzLLslEUYYx3ux3GePIcMQwNITQtuyiKr92O4/wsPz4+Frsiy7KX5XJbbItiu9lsVstVmqZJkiZJslwuNU3rdrunMg+hrqlG15rNZq7bM3Tt/uHJ6fXmSXLccYzINM0fToYQqghRFGXZzt1ggOROR0GCIPiDu4Hv9/teHM8wxpZlqaqKMS6KYvdJied50zIH/q3b99I0i8Jxv+85jjMaBb7nGaY1ncYYY9d1Hcf5IefhcFQURZIk8yTZbDbz+TyKotlsluf5YvEyiaIkSRuNxq9fv0RR5DgOQsiyrK7rJY7jeo6DFPniotxste7u7pGCmo1GpVoTId8mKKJ91b4m2+1rAECSJNPpNI7j6XR6eXlZIkny/Pz87Oy8Wq2Uy+Wzs7NyuVz9d6D6Tr1eq9VqlUrlpNoAgBIAgKZpQRD4dwRBUBRFlmWe5zmOO34hhARBGIbxXWYY5pBzGIZfVxIG4xuSYFmGurnJF8uvddu2T67qQx6Pxxjjt7ctxjjP04eHh+Fo+PT0tFqvi6LYbrc/3vNBBgB4/X6apLPZLAiCxeJltVod6vyyyPM8y7IoirIs03X9JOeDDCFEssQw3GTyjBSFZlgO8ixFiR1JQaqCFNftb97eer3eDydDntd1TeqIoiSHYWToWkeSPM87jJaqMoAxTGu33zuO89VhR/8zbK9/jHC9Xud5Povjl5dD0GmWxXGcZtmuKGzbPumwj4IFQTCLY0mSuoaxfn29Gwx4CMWO7Ht9w+ohWdJ0s16r//nzR1VVCOHt7S3GmKbpg0xRVLPRuLi4qP6rUhRN03T76qr6r3ZDEJfNq/ahw4hKpUIQxGQyvb+/bzabHzJBEK1Wi6IomqFJkry+bhMEQb1DkmS7fdVstq5arXq9fmySzWbDMMxH2JIk8TzHsowgiqZpyLIEIWQYFiEkCuI4CN/HY+H7vqZpGOP1ek1R1H6//5A1DVE0zXG8ghSe5ySpAziepimGppIsP5YnDMOjvNlsAAAYY5ZlD/O8Wq1OBvU7x/aMoogkyd+/f0MI//79a1lWvV4vCYIwGj46Ts/sdh3XtW0zGI/dvmdbBhSk4Wh0/EUURTc3NyRJdrtdz/MsywrDsCTLsmlagKZlpNq2JYiCoWtCR5nN52mar19fv+Qf3jAAAEKqrqpQFB3bRqqK0OHlfhqNnp+fgyAYDodhGBqGgRD6/obt9/uS53mG0bVs27KsrmFYn2iaekR7R1XVIAhOTv4PWHx0T52XXW4AAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;post prototype memory stack&quot; title=&quot;post prototype memory stack&quot; src=&quot;/static/41636f46f9c6e624e43302ac64aa27ac/16caa/post_prototype_memory_stack.png&quot; srcset=&quot;/static/41636f46f9c6e624e43302ac64aa27ac/c26ae/post_prototype_memory_stack.png 158w,
/static/41636f46f9c6e624e43302ac64aa27ac/6bdcf/post_prototype_memory_stack.png 315w,
/static/41636f46f9c6e624e43302ac64aa27ac/16caa/post_prototype_memory_stack.png 339w&quot; sizes=&quot;(max-width: 339px) 100vw, 339px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
&lt;p&gt;Reduced memory consumption is one advantage of keeping a reference to a prototype instead of a complete copy. Another advantage is that if additions are made to the Prototype, the changes will be extended to all instances.&lt;/p&gt;
&lt;p&gt;Awesome.&lt;/p&gt;</content:encoded></item><item><title><![CDATA['in' operator avoids false falsies]]></title><description><![CDATA[I have encountered more than my share of javascript errors because I have made assumptions about the object I am working with, such as…]]></description><link>http://katieleonard.ca/blog/2014/2014-08-05-in-operator-avoid-false-falsies/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2014/2014-08-05-in-operator-avoid-false-falsies/</guid><pubDate>Tue, 05 Aug 2014 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I have encountered more than my share of javascript errors because I have made assumptions about the object I am working with, such as assuming that an object contains a property, and that I can call methods on that property:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; myObject&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token literal-property property&quot;&gt;TypeError&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Cannot read property &lt;span class=&quot;token string&quot;&gt;&apos;0&apos;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;undefined&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This line contains four assumptions, and therefore four places it can fail:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;myObject&lt;/code&gt; exists&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;myObject&lt;/code&gt; contains a property called &lt;code class=&quot;language-text&quot;&gt;data&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;data&lt;/code&gt; is an array&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;data&lt;/code&gt; is non-empty&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Presuming that if &lt;code class=&quot;language-text&quot;&gt;myObject&lt;/code&gt; does not exist means you have bigger problems, it is easy to fall into the trap of checking for the existence of a property by gating a conditional with it:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;myObject&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;//do something important with the data&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This technique will work in development, but the voice of experience tells us that it will not work in production. The reason it will not work is that javascript has more falsy values than most languages. Falsy values include the number zero, empty strings, null, undefined, NaN, and of course, the boolean false. So, if it is possible &lt;code class=&quot;language-text&quot;&gt;myObject.data&lt;/code&gt; to contain derived information, you have signed up to troubleshoot some unexpected behaviour.&lt;/p&gt;
&lt;p&gt;Fortunately, javascript has provided a failsafe way to check the existence of a property, regardless of the data it contains. The &lt;code class=&quot;language-text&quot;&gt;in&lt;/code&gt; operator checks if the key exists in the object’s hash table, and doesn’t care if it is a prototype or singleton property.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; myObject &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;undefined&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;data&apos;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; myObject
&lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;

&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; myObject&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;data &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;&apos;&lt;/span&gt;
&lt;span class=&quot;token string&quot;&gt;&quot;&quot;&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;data&apos;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; myObject
&lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; myObject&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;data &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;
&lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;(&apos;data&apos; in myObject)&lt;/code&gt; returns false if the property is undefined. If the property is defined, it returns true even if data contains a falsy value.&lt;/p&gt;
&lt;h3&gt;Resources&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;http://www.amazon.com/Principles-Object-Oriented-JavaScript-Nicholas-Zakas/dp/1593275404/ref=sr_1_1?ie=UTF8&amp;#x26;qid=1407339036&amp;#x26;sr=8-1&amp;#x26;keywords=principles+of+object+oriented+javascript&quot;&gt;The principles of object-oriented javascript&lt;/a&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[stringify cyclic structures with censors]]></title><description><![CDATA[Troubleshooting a d3 data visualization sometimes requires visual inspection of the underlying JSON data structure. You can convert linear…]]></description><link>http://katieleonard.ca/blog/2014/2014-07-23-stringify-cyclic-structures-with-censors/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2014/2014-07-23-stringify-cyclic-structures-with-censors/</guid><pubDate>Wed, 23 Jul 2014 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Troubleshooting a d3 data visualization sometimes requires visual inspection of the underlying JSON data structure. You can convert linear data structures to a JSON string using &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;JSON.stringify&lt;/code&gt;&lt;/a&gt;&lt;!--more--&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; x &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;JSON&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;stringify&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;x&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token string&quot;&gt;&quot;{}&quot;&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; x&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;y &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;1&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;2&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;3&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;JSON&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;stringify&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;x&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token string&quot;&gt;&quot;{&quot;&lt;/span&gt;y&lt;span class=&quot;token string&quot;&gt;&quot;:[&quot;&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;,&quot;&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;,&quot;&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;]}&quot;&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; x&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;z &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token literal-property property&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;b&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;c&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;JSON&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;stringify&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;x&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token string&quot;&gt;&quot;{&quot;&lt;/span&gt;y&lt;span class=&quot;token string&quot;&gt;&quot;:[&quot;&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;,&quot;&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;,&quot;&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;],&quot;&lt;/span&gt;z&lt;span class=&quot;token string&quot;&gt;&quot;:{&quot;&lt;/span&gt;a&lt;span class=&quot;token string&quot;&gt;&quot;:[&quot;&lt;/span&gt;b&lt;span class=&quot;token string&quot;&gt;&quot;,&quot;&lt;/span&gt;c&lt;span class=&quot;token string&quot;&gt;&quot;]}}&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Data structures that contain both upstream and downstream links between objects are cyclic structures. From the docs:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;JSON does not support cyclic structures.  Attempting to convert such an object into JSON format will result in a TypeError exception.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; x &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  y &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  x&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;children &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;y&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
  y&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;parent &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; x
Object &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token literal-property property&quot;&gt;children&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Object&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;JSON&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;stringify&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;x&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token literal-property property&quot;&gt;TypeError&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Converting circular structure to &lt;span class=&quot;token constant&quot;&gt;JSON&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;How can I look at a tree, or double-linked list data structure that is rife with circular links? JSON.stringify() takes a second argument called a censor in the docs. The censor is the programmatic court of appeal for whenever a cyclic structure is encountered:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;censor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;key&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; value&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;typeof&lt;/span&gt; value &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;object&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;undefined&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; value&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Of course, this approach will eliminate most of the tree structure by removing all objects from the JSON. Certainly we can return something more creative than &lt;code class=&quot;language-text&quot;&gt;undefined&lt;/code&gt;…&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;censor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;key&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; value&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;value &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;typeof&lt;/span&gt; value &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;object&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; value&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;parent&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    value&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;parent &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; value&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;parent&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; value&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In this censor, we replace the parent object with the parent’s name, and JSON.stringify has no complaints:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;censor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;key&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; value&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;value &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;typeof&lt;/span&gt; value &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;object&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; value&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;parent&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    value&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;parent &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; value&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;parent&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; value&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; x &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token literal-property property&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Theodore&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
Object &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token literal-property property&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Theodore&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; y &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token literal-property property&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Alvin&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
Object &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token literal-property property&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Alvin&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; x&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;children &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;y&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Object&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; y&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;parent &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; x
&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; Object &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token literal-property property&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Theodore&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;children&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Array&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;JSON&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;stringify&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;x&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token literal-property property&quot;&gt;TypeError&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Converting circular structure to &lt;span class=&quot;token constant&quot;&gt;JSON&lt;/span&gt;

&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;JSON&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;stringify&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;x&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; censor&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token string&quot;&gt;&quot;{&quot;&lt;/span&gt;name&lt;span class=&quot;token string&quot;&gt;&quot;:&quot;&lt;/span&gt;Theodore&lt;span class=&quot;token string&quot;&gt;&quot;,&quot;&lt;/span&gt;children&lt;span class=&quot;token string&quot;&gt;&quot;:[{&quot;&lt;/span&gt;name&lt;span class=&quot;token string&quot;&gt;&quot;:&quot;&lt;/span&gt;Alvin&lt;span class=&quot;token string&quot;&gt;&quot;,&quot;&lt;/span&gt;parent&lt;span class=&quot;token string&quot;&gt;&quot;:&quot;&lt;/span&gt;Theodore&lt;span class=&quot;token string&quot;&gt;&quot;}]}&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Awesome.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[jQuery-UI and meteor]]></title><description><![CDATA[I have been working on Virtual Playbill for the last few weeks using meteor, bootstrap, and a number of other UI packages. I wanted to use a…]]></description><link>http://katieleonard.ca/blog/2014/2014-06-16-jquery-ui-and-meteor/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2014/2014-06-16-jquery-ui-and-meteor/</guid><pubDate>Mon, 16 Jun 2014 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I have been working on &lt;a href=&quot;virtualplaybill.net&quot;&gt;Virtual Playbill&lt;/a&gt; for the last few weeks using meteor, bootstrap, and a number of other UI packages. I wanted to use a datepicker as a form field, but getting jQuery-ui working was not a straightforward package download as many other features are. There are currently 5 packages available for installation on &lt;a href=&quot;https://atmospherejs.com/package/jquery-ui?q=jquery-ui&quot;&gt;Atmosphere&lt;/a&gt; (the meteor package manager), and I attempted several of them before finding the combination that worked&lt;!--more--&gt;:&lt;/p&gt;
&lt;h3&gt;1. Install the jQuery-ui package from &lt;a href=&quot;https://atmospherejs.com/package/jquery-ui&quot;&gt;Atmosphere&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;mrt add jquery-ui&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;2. Download jQuery-ui&lt;/h3&gt;
&lt;p&gt;For me, the meteorite package did not properly install the css or images I needed to get the datepicker working, so I downloaded &lt;a href=&quot;http://jqueryui.com/&quot;&gt;jquery-ui&lt;/a&gt;, swiped the css file (un-minified), and added it to my &lt;code class=&quot;language-text&quot;&gt;client/stylesheets&lt;/code&gt; folder.&lt;/p&gt;
&lt;h3&gt;3. Add jQuery-ui images&lt;/h3&gt;
&lt;p&gt;The css styled the datepicker calendar perfectly, except for the previous month and next month buttons. jQuery-ui comes with a few standard icons, so I placed the jQuery-ui images folder in &lt;code class=&quot;language-text&quot;&gt;/public&lt;/code&gt;, since static files must be kept in a public folder for meteor to acknowledge them.&lt;/p&gt;
&lt;h3&gt;4. Relocate the images&lt;/h3&gt;
&lt;p&gt;The jQuery-ui css file tries to locate the images in its parent folder, but as I mentioned, static assets = public folder. The advantage of the public folder is that all assets can be referenced with a leading slash: &lt;code class=&quot;language-text&quot;&gt;/images&lt;/code&gt;. I scanned the un-minified version of the css and changed the image url locations from &lt;code class=&quot;language-text&quot;&gt;images/...&lt;/code&gt; to &lt;code class=&quot;language-text&quot;&gt;/images/...&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Voila! A beautiful, functional datepicker!&lt;/p&gt;
&lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 282px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/a192d88db1000a8b0224a24947e6d394/cd13f/post_datepicker.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 113.9240506329114%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAXCAIAAACEf/j0AAAACXBIWXMAAAsTAAALEwEAmpwYAAADq0lEQVQ4y41QS2skVRgtxN8ibtxlMaC4Exfi6CjoGEUUcaOIW4X5AcqgGUfcKYhuJiA6IzPpJN3JZNIJSabT6Tw66XRX1/NW1X2/uqq6qtOdjlSSQQMO5ONwL9+593C+7xi59OL6VLJ16wLq3ye1b5PNm6ftVNFuTf0HPyS1b1K/amRuOX/06XDls/yPF/K7Vwr8OTGYuzZc+fxocfJo6ePh6heD8ruDv18e3HtxcO+lwV9XBuV3Rmtfpo1bRgbr6fz1rPJ+ev+1fO7Nfulqf+b1vDKZLn6SPfwoX/gwLX+QVyb7pWvpzBv53Fvpg6tZ+b1s7u2k+ZsRx3G3te1aBxGwWs0t4Jme1Wo16wh02nubnYNtBMxmY92z24HbOdhroNC12nt2Z5cRZCitl5cfLSwtd8zu9PT0eq3eabcfzMyaljM/P3/3fsl23EploeA75tz8Ytdyq9VqeeFhFEGDc961LMd1bdsGwLds23Ec1/Msy/J9H/i+bVme7zuOY9t2AIBt247rWpbtA2BwIZQUXchCiKTu7biRFDziqumG/Z5qAuJFSGvdcCBjFFC57QT9nj4MqRNEhtaaUoophQhywf0IUUK44CCCgjNEWASREAJATAihjHsh5Oy8jDhOEq22POQjJlSy5RAlxaZHWgAppTZdzBizENvxoJLiMGJNH/a0qpoQc1mkzRn1EUWwm6g2Im1GiYuoF0LGGMCUYAwpc0JEKYGEuSHknDkRZpwbSZJwIdYskvIKt2+7uz9pRVshN0Pc02rZjCChHuY1B55NtO9DpVTNRUKeOlNKOiHVZCkJf8Xm74whgIv8OGOHAIcQQXLmTA8DbAeQMtYJkBSicKZcPHYQZ8TGZD+ItBT7QfGslNqwEWXMRbzhIS1FG7JDgHpKVc0Is1MxprThQkyoDVkbFIZNgK0AMc4f25BQYkVk2404Y62g4Dnnq2ZI+Jkz4+tWhCl1ENtxoRCip6SUQgiR6OLSUsZKnvHqCa+1NtIkRoSsdUNKsBnihhNKfl7iySkutowxyqiU0hDJgMher5dSFQudKJ1QFT8NWMa8l2ZZP+33szw3eDY+Hp9cso5GJyIrfp8pDJWPdT6OB+fQ2Vhlx/8LnR2L/nE8+NfKODoes/6IpkOajnh/lA3Hw9H46Gm4OKRxewU9/93Oq78cvPLz/nM3d35cRScnJ8PLbWLcuAOendyY+Gp34uu9Z65v3Ljjn+52OXFA81KNz9bF7KYo1XhA8yKPy0X4D2/ewngFj5HhAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;post datepicker&quot; title=&quot;post datepicker&quot; src=&quot;/static/a192d88db1000a8b0224a24947e6d394/cd13f/post_datepicker.png&quot; srcset=&quot;/static/a192d88db1000a8b0224a24947e6d394/c26ae/post_datepicker.png 158w,
/static/a192d88db1000a8b0224a24947e6d394/cd13f/post_datepicker.png 282w&quot; sizes=&quot;(max-width: 282px) 100vw, 282px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;</content:encoded></item><item><title><![CDATA[helpers calling helpers]]></title><description><![CDATA[Whittling away at the Discover Meteor tutorial for creating a social news sharing site, I was implementing a Comments collection and related…]]></description><link>http://katieleonard.ca/blog/2014/2014-06-03-helpers-calling-helpers/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2014/2014-06-03-helpers-calling-helpers/</guid><pubDate>Tue, 03 Jun 2014 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Whittling away at the Discover Meteor tutorial for creating a social news sharing site, I was implementing a Comments collection and related accoutrements (templates, helpers, forms, etc.) when I uncovered a need to call one helper method from another&lt;!--more--&gt;.&lt;/p&gt;
&lt;p&gt;I was using this handy method to return the number of comments made on a particular post:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;Template.postPageItem.helpers({
  commentsCount: function() {
    return Comments.find({postId: this._id}).count();
  }
});&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;submitted by {{postAuthor}}, with
&amp;lt;a href=&quot;{{pathFor &apos;postPage&apos;}}&quot;&gt;{{commentsCount}} comments&amp;lt;/a&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Which returned a very ordinary:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;submitted by meImAnAwesomeUser, with 1 comments&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;1 &lt;strong&gt;comments&lt;/strong&gt;?! That makes no sense.. I didn’t minor in English so I could let that travesty fly. I made a new helper method:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;Template.postPageItem.helpers({
  commentsCount: function() {
    return Comments.find({postId: this._id}).count();
  },
  commentsNote: function() {
    return Comments.find({postId: this._id}).count() === 1 ? &quot;comment&quot; : &quot;comments&quot;;
  }
});&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;UGH! What is that on line 6? Possibly the ugliest ternary statement I have written today (probably). Is that code duplication I smell? Won’t reusing &lt;code class=&quot;language-text&quot;&gt;commentsCount&lt;/code&gt; remove the redundancy?&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;Template.postPageItem.helpers({
  commentsCount: function() {
    return Comments.find({postId: this._id}).count();
  },
  commentsNote: function() {
    return commentsCount === 1 ? &quot;comment&quot; : &quot;comments&quot;;
  }
});&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Only.. that doesn’t work:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;Exception from Deps recompute function: ReferenceError: commentsCount is not defined
at Object.Template.postPageItem.helpers.commentsNote (http://localhost:3000/client/views/posts/post_page_item.js?160ec9a926881c795377a47c15affc4f553c4d88:9:12)&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;But it is RIGHT ABOVE! I can see it! It is in the same file! I tried all permutations of &lt;code class=&quot;language-text&quot;&gt;commentsCount()&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;this.commentsCount&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;self.commentsCount&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;this.self.commentsCount()&lt;/code&gt;, and they all threw either similar errors or &lt;code class=&quot;language-text&quot;&gt;undefined&lt;/code&gt;. Calling the prototype method directly turns out to work just fine:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;Template.postPageItem.helpers({
  commentsCount: function() {
    return Comments.find({postId: this._id}).count();
  },
  commentsNote: function() {
    var count = Template.postPageItem.commentsCount()
    return count === 1 ? &quot;comment&quot; : &quot;comments&quot;;
  }
});&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Except that when &lt;code class=&quot;language-text&quot;&gt;commentsCount&lt;/code&gt; is called on line 6, &lt;code class=&quot;language-text&quot;&gt;this&lt;/code&gt; is no longer the lovely Post item provided by the template. No, &lt;code class=&quot;language-text&quot;&gt;this&lt;/code&gt; becomes the context of the &lt;code class=&quot;language-text&quot;&gt;commentsNote&lt;/code&gt; function, and therefore calling &lt;code class=&quot;language-text&quot;&gt;this._id&lt;/code&gt; will return &lt;code class=&quot;language-text&quot;&gt;undefined&lt;/code&gt;. The closure issue can be worked around with a little argument passing:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;Template.postPageItem.helpers({
  commentsCount: function(id) {
    var count_id = typeof id !== &apos;undefined&apos; ? id : this._id;
    return Comments.find({postId: count_id}).count();
  },
  commentsNote: function() {
    var count = Template.postPageItem.commentsCount(this._id)
    return count === 1 ? &quot;comment&quot; : &quot;comments&quot;;
  }
});&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Wow. Passing in the id works, but now I have to check the context to determine the appropriate id. That is the most unreadable-but-reused code I have written today (probably), and I learned some valuable lessons on this frantic search for DRY:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;self&lt;/code&gt;, whether called from a helper or the console, will always be &lt;code class=&quot;language-text&quot;&gt;window&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;this&lt;/code&gt; called from a Template helper refers to the item of the collection that is passed in to the template&lt;/li&gt;
&lt;li&gt;because helper methods are closures, &lt;code class=&quot;language-text&quot;&gt;this&lt;/code&gt; in the calling method is different from &lt;code class=&quot;language-text&quot;&gt;this&lt;/code&gt; in the called method&lt;/li&gt;
&lt;li&gt;don’t dry out your code to the point of unreadability&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In the end, cleaning up the ugly ternary makes the code reuse more reasonable.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;Template.postPageItem.helpers({
  commentsCount: function() {
    return Comments.find({postId: this._id}).count();
  },
  commentsNote: function() {
    var count = Comments.find({postId: this._id}).count();
    return count === 1 ? &quot;comment&quot; : &quot;comments&quot;;
  }
});&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Awesome.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[flash your local collection]]></title><description><![CDATA[Rails allows you to pass messages to the user between actions (“This ActionDispatch::Flash will self-destruct”), and because Rails, all the…]]></description><link>http://katieleonard.ca/blog/2014/2014-05-26-flash-your-local-collection/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2014/2014-05-26-flash-your-local-collection/</guid><pubDate>Mon, 26 May 2014 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Rails allows you to pass messages to the user between actions (“This &lt;a href=&quot;http://api.rubyonrails.org/classes/ActionDispatch/Flash.html&quot;&gt;ActionDispatch::Flash&lt;/a&gt; will self-destruct”), and because Rails, all the message generation happens server side:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;def show
  flash[:notice] = &quot;You dropped your packet.&quot;
end&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Meteor is mostly a client-side application framework, and you can implement a similar message system, which will never touch the server, by defining a collection that is local to the browser.&lt;!--more--&gt;&lt;/p&gt;
&lt;h3&gt;1. Create a local collection&lt;/h3&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;Errors = new Meteor.Collection(null);&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Passing &lt;code class=&quot;language-text&quot;&gt;null&lt;/code&gt; into the Collection declaration tells Meteor that the collection should not be extended to the server — it creates an “unmanaged (unsynchronized) local collection” (&lt;a href=&quot;http://docs.meteor.com/#meteor_collection&quot;&gt;docs&lt;/a&gt;)&lt;/p&gt;
&lt;h3&gt;2. Throw an error whenever you need to&lt;/h3&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;if(error){
  Errors.insert({message: error.reason});
}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;3. Create a template for displaying the error&lt;/h3&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;&amp;lt;template name=&quot;errors&quot;&gt;
  &amp;lt;div class=&quot;errors&quot;&gt;
    {{#each errors}}
      {{&gt; error}}
    {{/each}}
  &amp;lt;/div&gt;
&amp;lt;/template&gt;

&amp;lt;template name=&quot;error&quot;&gt;
  &amp;lt;div class=&quot;alert alert-error&quot;&gt;
    &amp;lt;button type=&quot;button&quot; class=&quot;close&quot; data-dismiss=&quot;alert&quot;&gt;&amp;amp;times;&amp;lt;/button&gt;
    {{message}}
  &amp;lt;/div&gt;
&amp;lt;/template&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;4. Create a helper method for serving the errors to the template&lt;/h3&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;...
Template.errors.helpers({
  errors: function() {
    return Errors.find();
  }&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Every template that contains the handlebars &lt;code class=&quot;language-text&quot;&gt;{{&gt; errors}}&lt;/code&gt; will now display whatever errors have been saved to the session collection.&lt;/p&gt;
&lt;p&gt;Awesome.&lt;/p&gt;
&lt;h3&gt;Resources&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://www.discovermeteor.com/&quot;&gt;discovermeteor.com&lt;/a&gt;
&lt;a href=&quot;http://docs.meteor.com&quot;&gt;Meteor docs&lt;/a&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[meteor sessions]]></title><description><![CDATA[Session stores information that relates to a single user’s instance of your application “global reactive data store”:
** there is only one…]]></description><link>http://katieleonard.ca/blog/2014/2014-05-10-slash-meteor-sessions/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2014/2014-05-10-slash-meteor-sessions/</guid><pubDate>Sat, 10 May 2014 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;Session&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;stores information that relates to a single user’s instance of your application&lt;/li&gt;
&lt;li&gt;“global reactive data store”:
** there is only one session per application instance
** the information in the session is as reactive as the database information store&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Set a session variable&lt;/h2&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;&gt; Session.set(&apos;myVariable&apos;, &apos;myVariableValue&apos;);&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Retrieving a session variable&lt;/h2&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;&gt; Session.get(&apos;myVariable&apos;);&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Autorun&lt;/h2&gt;
&lt;p&gt;Yes, the session is a reactive data store, meaning it can be altered or added to at will. Why doesn’t it automagically update my UI? Because the &lt;strong&gt;context&lt;/strong&gt; in which the Session is altered or added to may not be a reactive context. When the application is opened for the first time, the Session is read from and added to as the application code is loaded, but unless the Session changes are included in an Autorun block, meaning it is re-run every time there are changes made to it, the Session and all its fancy state-ness is only loaded the once.&lt;/p&gt;
&lt;!--more--&gt;
&lt;h2&gt;Lessons about sessions&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Always store user state in the Session or the URL so that users are minimally disrupted when a hot code reload happens.&lt;/li&gt;
&lt;li&gt;Store any state that you want to be shareable between users within the URL itself.&lt;/li&gt;
&lt;/ol&gt;</content:encoded></item><item><title><![CDATA[mongo trouble? reset!]]></title><description><![CDATA[Back in March I wrote about letting my computer’s battery die in the middle of a meteor project, with the consequence being that I could not…]]></description><link>http://katieleonard.ca/blog/2014/2014-05-03-mongo-trouble-reset/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2014/2014-05-03-mongo-trouble-reset/</guid><pubDate>Sat, 03 May 2014 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Back in March I wrote about letting my computer’s battery die in the middle of a meteor project, with the consequence being that I could not connect to the underlying mongo database:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ meteor
[[[[[ ~/project/in/progress ]]]]]

=&gt; Started proxy.
Unexpected mongo exit code 100. Restarting.
Unexpected mongo exit code 100. Restarting.
Unexpected mongo exit code 100. Restarting.
Can&apos;t start Mongo server.
MongoDB had an unspecified uncaught exception.
This can be caused by MongoDB being unable to write to a local database.
Check that you have permissions to write to .meteor/local. MongoDB does
not support filesystems like NFS that do not allow file locking.&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;After much spelunking in stackoverflow and documentation, I discovered the magic of this command:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ sudo -u mongodb mongdo --repair --dbpath /var/lib/mongodb
$ sudo service mongodb start&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Repairing and restarting the mongo service seemed to do the trick, and I continued on my merry meteor way. Well, I did it again — I let my battery die in the middle of a meteor project, and with feelings of smug satisfaction, I plumbed my blog archive for the answer. Only this time the magic antidote didn’t work&lt;!--more--&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ sudo -u mongodb mongod --repair --dbpath /var/lib/mongodb/
[sudo] password for keighty:
Sat May  3 09:52:04.793 [initandlisten] finished checking dbs
Sat May  3 09:52:04.793 dbexit:
Sat May  3 09:52:04.793 [initandlisten] shutdown: going to close listening sockets...
Sat May  3 09:52:04.793 [initandlisten] shutdown: going to flush diaglog...
Sat May  3 09:52:04.793 [initandlisten] shutdown: going to close sockets...
Sat May  3 09:52:04.793 [initandlisten] shutdown: waiting for fs preallocator...
Sat May  3 09:52:04.793 [initandlisten] shutdown: closing all files...
Sat May  3 09:52:04.793 [initandlisten] closeAllFiles() finished
Sat May  3 09:52:04.793 [initandlisten] shutdown: removing fs lock...
Sat May  3 09:52:04.794 dbexit: really exiting now

$ sudo service mongodb start
mongodb start/running, process 2415
$ meteor
[[[[[ ~/project/in/progress ]]]]]

=&gt; Started proxy.
Unexpected mongo exit code 100. Restarting.
Unexpected mongo exit code 100. Restarting.
Unexpected mongo exit code 100. Restarting.
Can&apos;t start Mongo server.
MongoDB had an unspecified uncaught exception.
This can be caused by MongoDB being unable to write to a local database.
Check that you have permissions to write to .meteor/local. MongoDB does
not support filesystems like NFS that do not allow file locking.&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;C’mon — It worked the last time! I tried it again with the same result. I tried &lt;code class=&quot;language-text&quot;&gt;chown&lt;/code&gt;-ing the local db. I tried &lt;code class=&quot;language-text&quot;&gt;chown&lt;/code&gt;-ing the database in &lt;code class=&quot;language-text&quot;&gt;/var/lib/mongodb&lt;/code&gt;. After each attempted solution the mongobd service would start, but meteor hiccuped on writing to the database. So I tried something radical. Something that wasn’t in any of the manuals, or any of the &lt;a href=&quot;http://stackoverflow.com/questions/5798549/why-cant-i-start-the-mongodb&quot;&gt;responses to similar questions&lt;/a&gt; on stackoverflow:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ meteor reset
Project reset.
$ meteor
[[[[[ ~/project/in/progress ]]]]]

=&gt; Started proxy.
=&gt; Started MongoDB.
=&gt; Started your app.

=&gt; App running at: http://localhost:3000/&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Turns out that if you hard shut-down your computer while your meteor project’s mongo instance is running, it remains in a locked mode. Since it was only a development database I took a chance that dropping it would cure my ills. Voila! Meteor and mongodb are friends again.&lt;/p&gt;
&lt;p&gt;Awesome.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[meteor, fetch!]]></title><description><![CDATA[From Discover Meteor: find() returns a cursor, which is a reactive data source. Data from reactive sources will be updated automatically to…]]></description><link>http://katieleonard.ca/blog/2014/2014-03-31-meteor-fetch/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2014/2014-03-31-meteor-fetch/</guid><pubDate>Mon, 31 Mar 2014 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;From &lt;a href=&quot;http://book.discovermeteor.com/&quot;&gt;Discover Meteor&lt;/a&gt;: find() returns a cursor, which is a reactive data source.&lt;/p&gt;
&lt;p&gt;Data from reactive sources will be updated automatically to track changes in the data used to generate it. &lt;!--more--&gt;Cursors are derived from specific sources:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Session variables&lt;/li&gt;
&lt;li&gt;Database queries on Collections&lt;/li&gt;
&lt;li&gt;Meteor.status&lt;/li&gt;
&lt;li&gt;The ready() method on a subscription handle&lt;/li&gt;
&lt;li&gt;Meteor.user&lt;/li&gt;
&lt;li&gt;Meteor.userId&lt;/li&gt;
&lt;li&gt;Meteor.loggingIn&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;&amp;amp;gt; Posts.find()
LocalCollection.Cursor {collection: LocalCollection, sorter: null, _selectorId: undefined, matcher: Minimongo.Matcher, skip: undefined…}
      _selectorId: undefined
      _transform: null
      collection: LocalCollection
      cursor_pos: 0
      db_objects: null
      fields: undefined
      limit: undefined
      matcher: Minimongo.Matcher
      reactive: true
      skip: undefined
      sorter: null
      __proto__: Object&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Cursors are not query snapshots. They are query snapshot containers — the contents of which are updated by changes to the underlying data. To interact with the data contained in a cursor, we can use fetch() to transform the cursor into an array.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;&amp;amp;gt; Posts.find().fetch()
[
    Object
    _id: &quot;z4z36DFCaGr8Ptuqd&quot;
    title: &quot;The Way We Live Now&quot;
    author: &quot;Anthony Trollope&quot;
    __proto__: Object
    ...
]&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Meteor can iterate over a cursor without first converting it to an array, but in order to interact with the data directly, you must first use fetch(), map(), or forEach(). For more cursor fun, checkout the &lt;a href=&quot;http://docs.meteor.com/#reactivity&quot;&gt;Meteor docs&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Awesome.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[situations matter]]></title><description><![CDATA[Situations Matter by Sam Sommers is an eye-opening study of the influence of context on human interactions. Social psychologists call it…]]></description><link>http://katieleonard.ca/blog/2014/2014-03-28-situations-matter/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2014/2014-03-28-situations-matter/</guid><pubDate>Fri, 28 Mar 2014 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;http://www.amazon.com/Situations-Matter-Understanding-Context-Transforms-ebook/dp/B005ERIS5S/ref=sr_1_1?ie=UTF8&amp;#x26;qid=1396016834&amp;#x26;sr=8-1&amp;#x26;keywords=situations+matter&quot;&gt;Situations Matter&lt;/a&gt; by Sam Sommers is an eye-opening study of the influence of context on human interactions. Social psychologists call it “fundamental attribution error”, which is a tendency to interpret someone else’s behavior as stemming from their core characteristics, rather than to external circumstances. A simplistic example of attribution error is assuming that the person driving the speeding car is a reckless speed-freak rather than someone rushing a woman in labor to the hospital. Sommers has studied the power of situations over human interactions and how the attribution error interferes with our ability to empathize with the unfamiliar. I have read similar studies of how bias infiltrates our relationships, but what surprised me the most is how it also influences our perception of the self. &lt;!--more--&gt;&lt;/p&gt;
&lt;h3&gt;You’re not the person you thought you were&lt;/h3&gt;
&lt;p&gt;A provocative but aptly named chapter, Sommers overturns the concept of an “authentic self” with a simple fill-in-the-blanks exercise:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;I am &lt;strong&gt;&lt;strong&gt;&lt;strong&gt;&lt;strong&gt;_&lt;/strong&gt;&lt;/strong&gt;&lt;/strong&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;I am &lt;strong&gt;&lt;strong&gt;&lt;strong&gt;&lt;strong&gt;_&lt;/strong&gt;&lt;/strong&gt;&lt;/strong&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;I am &lt;strong&gt;&lt;strong&gt;&lt;strong&gt;&lt;strong&gt;_&lt;/strong&gt;&lt;/strong&gt;&lt;/strong&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;I am &lt;strong&gt;&lt;strong&gt;&lt;strong&gt;&lt;strong&gt;_&lt;/strong&gt;&lt;/strong&gt;&lt;/strong&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;I am &lt;strong&gt;&lt;strong&gt;&lt;strong&gt;&lt;strong&gt;_&lt;/strong&gt;&lt;/strong&gt;&lt;/strong&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;His study subjects were required to fill in 20 of these blanks, but 5 is enough to illustrate his point to the reader. The open-endedness of this exercise allows for a fantastic range of responses: “I am 36 years old, I am hungry, I am tall, I am a lifelong learner”. Taking the 20 questions test in different contexts will yield different definitions of yourself. Sommers has discovered that “we tend to think of ourselves in terms of that which makes us distinctive”, so your answers will have more to do with the people around you than with a fixed set of characteristics. A woman is more likely to include gender on her list if she is in a room full of men than if she is in a room full of women. So it seems that “identity is malleable and personal preferences are constructed on the spot.” Introspection will gain us little but a hazy snap-shot of our identity at any given moment.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“It’s refreshing to realize that you’re not a finished product — that who you are in the here and now may not be the same person you’ll be in the then and there. In fact, it’s the opposite view of the self as a fixed entity that causes problems. When you assume that there’s a true core self waiting to be discovered, that’s when your potential seems limited and the world around you is full of threats to be rationalized away.”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;One quality that is typically presumed to be fixed is intelligence. Challenging this truism, another study was conducted where students were grouped according to their belief that either intelligence is a stable attribute, or that their intellect can be changed. The researchers asked the students to predict the likelihood that they will attend a remedial language course, and then tracked their performance. It was found that among the students who fared poorly in the language course, those who viewed intelligence as a permanent, unchangeable trait were less likely to enroll in the remedial course — that is, to take steps in order to improve their performance. For students who believe that intelligence is fixed, a poor exam grade is a mark of their limitations rather than an opportunity for improvement. Students who believe that intelligence is malleable are more likely to show the stick-to-itiveness necessary for self-improvement.&lt;/p&gt;
&lt;p&gt;Viewing the self less like a rigid Rubik’s Cube to be solved, and more like Silly Putty that conforms to the shape of its container, will likely free up a lot of my time. Instead of trying to solve the puzzle. I can spend energy on finding the container that makes me happy… for the moment.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[the ambition gap - leaning in]]></title><description><![CDATA[I may be a little late to the game, but I am finally reading Sheryl Sandberg’s “Lean In”, and right from the introduction I can understand…]]></description><link>http://katieleonard.ca/blog/2014/2014-03-23-the-ambition-gap-lean-in/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2014/2014-03-23-the-ambition-gap-lean-in/</guid><pubDate>Sun, 23 Mar 2014 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I may be a little late to the game, but I am finally reading Sheryl Sandberg’s “Lean In”, and right from the introduction I can understand why it caused such a stir when it came out in 2012. Sandberg addresses the issue of why there are relatively few women in leadership roles, and ways that women have held themselves back.&lt;!--more--&gt; Women earn more than 57% of undergraduate degrees and 60% of masters degrees, and yet hold less than 14% of C level positions. I always assumed that as women disproportionately fill the ranks of entry level positions, there would be a proportional increase of women filling senior level positions as well. Apparently this is not the case. “The exodus of highly educated women is a major contributor to the leadership gap.”&lt;/p&gt;
&lt;p&gt;Sandberg shares a story about a kindergarten class where the students were asked “What do you want to be when you grow up?“. Several of the boys wanted to be president, but none of the girls did. This disparity continues into middle school, where more boys than girls aspire to leadership roles in future careers. {“36% of men want to reach the C-suite and only 18% of women.“} Why so few? If the question were ever posed to me I would honestly say that rising to the C-levels has never been of any interest, and I think Sandberg is right to ask why.&lt;/p&gt;
&lt;h3&gt;Too much Barbie or not enough Hillary?&lt;/h3&gt;
&lt;p&gt;Sandberg is quick to link the relative derth of women in leadership roles on the messages of obedience and passivity we instill in girls and the general indulgence of opposite traits in boys (“boys will be boys”). “Gender stereotypes introduced in childhood are reinforced throughout our lives and become self-fulfilling prophesies.” While gender stereotypes have held women back in the past, today the difference is in their perceived options, not in perceived abilities. When the kindergarten-ers in Sandberg’s story were asked what they wanted to be when they grew up they looked to the immediate role models around them. Call it a lack of imagination about one’s future career, rather than a lack of ambition.&lt;/p&gt;
&lt;p&gt;She has recently begun a campaign to &lt;a href=&quot;http://banbossy.com/&quot;&gt;ban the word “bossy”&lt;/a&gt;, and while words have the power to shape our values, it is a passive approach to solving the problem. Boys don’t show a propensity towards leadership in middle-school any more than girls show a propensity towards secretarial work. Sandberg’s &lt;a href=&quot;http://leanin.org/&quot;&gt;“Lean In”&lt;/a&gt; project comes closer to directly addressing the issue. She realizes that you can’t be what you can’t see”, and works to raise the profiles of powerful women. When it becomes normal to have female leaders, I am sure we will find more girls expressing ambition. Likewise, when it becomes normal for men to share equally in care-giving, boys will begin making different choices.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.amazon.com/Lean-In-Women-Work-Will/dp/0385349947/ref=sr_1_1?ie=UTF8&amp;#x26;qid=1395756488&amp;#x26;sr=8-1&amp;#x26;keywords=lean+in&quot;&gt;Lean In: Women, Work, and the Will to Lead&lt;/a&gt; by Sheryl Sandberg&lt;/p&gt;</content:encoded></item><item><title><![CDATA[line, spline]]></title><description><![CDATA[D3 lines are rendered using linear interpolation by default. This means that the line connecting a series of points will trace a direct path…]]></description><link>http://katieleonard.ca/blog/2014/2014-03-20-line-spline/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2014/2014-03-20-line-spline/</guid><pubDate>Thu, 20 Mar 2014 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;D3 lines are rendered using linear interpolation by default. This means that the line connecting a series of points will trace a direct path from one node to another:&lt;/p&gt;
&lt;div id=&quot;graph-here&quot;&gt;
  &lt;script src=&quot;https://mbostock.github.com/d3/d3.v2.min.js&quot;&gt;&lt;/script&gt;
  &lt;script&gt;
var width = 400,
    height = 400,
    margin = 5,
    scalex = d3.scale.linear().domain([0, 7]).range([margin, width - margin]),
    scaley = d3.scale.linear().domain([0, 7]).range([height - margin, margin]);
&lt;p&gt;var data = [
[
{x: 0, y: 5},{x: 1, y: 7},{x: 2, y: 5},
{x: 3, y: 5},{x: 4, y: 3},{x: 6, y: 4},
{x: 7, y: 2}
],
[
{x: 0, y: 3},{x: 1, y: 5},{x: 2, y: 3},
{x: 3, y: 3},{x: 4, y: 1},{x: 6, y: 2},
{x: 7, y: 1}
]
];&lt;/p&gt;
&lt;p&gt;var straightLine = d3.svg.line()
.interpolate(“linear”)
.x(function(d){return scalex(d.x);})
.y(function(d){return scaley(d.y);});
var smoothLine = d3.svg.line()
.interpolate(“cardinal”)
.x(function(d){return scalex(d.x);})
.y(function(d){return scaley(d.y);});&lt;/p&gt;
&lt;p&gt;var svg = d3.select(“#graph-here”).append(“svg”);&lt;/p&gt;
&lt;p&gt;  svg.attr(“height”, height)
.attr(“width”, width);&lt;/p&gt;
&lt;p&gt;   svg.selectAll(“path”)
.data(data)
.enter()
.append(“path”)
.attr(“class”, “line”)
.attr(“fill”, “none”)
.attr(“stroke”, “blue”)
.attr(“stroke-width”, 2)
.attr(“d”, function(d, i){
if(i % 2 === 0) return straightLine(d);
return smoothLine(d)
});&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;svg.selectAll(&quot;textPath&quot;).data(data)
  .enter()
    .append(&quot;text&quot;)
    .attr(&quot;x&quot;, function(d) { return scalex(d[d.length-2].x); })
    .attr(&quot;y&quot;, function(d) { return scaley(d[d.length-2].y); })
    .attr(&quot;text-anchor&quot;, &quot;end&quot;)
    .text(function(d, i) {
      if(i % 2 === 0) return &quot;Straight Lines&quot;;
      return &quot;Smooth Lines&quot;;
    });&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/script&gt;
&lt;/div&gt;
&lt;p&gt;The curved line is rendered with the cardinal interpolator, one of several options D3 provides. The curvature of the line is called a &lt;strong&gt;spline&lt;/strong&gt;. Splines are tools used by architects to draw curved lines, and the term was adopted by mathematicians to describe smooth, piecewise polynomial approximation:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Splines are curves, which are usually required to be continuous and smooth… [The] join points are called knots. Splines with few knots are generally smoother than splines with many knots; however, increasing the number of knots usually increases the fit of the spline function to the data. Knots give the curve freedom to bend to more closely follow the data. —&lt;a href=&quot;http://en.wikipedia.org/wiki/Spline_(mathematics)&quot;&gt;Wikipedia&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;</content:encoded></item><item><title><![CDATA[multiple remotes]]></title><description><![CDATA[Somehow I had worked out in my head that there could be only one remote. Origin. Turns out you can set and push to a (presumably) infinite…]]></description><link>http://katieleonard.ca/blog/2014/2014-03-19-multiple-remotes/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2014/2014-03-19-multiple-remotes/</guid><pubDate>Wed, 19 Mar 2014 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Somehow I had worked out in my head that there could be only one remote. Origin. Turns out you can set and push to a (presumably) infinite number of remote repositories &lt;!--more--&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ git config --list
push.default=nothing
alias.hist=log --pretty=format:&quot;%h %ad | %s%d [%an]&quot; --graph --date=short
user.name=Katie Leonard
…
remote.origin.url=git@github.com:keighty/thorfiles.git
remote.origin.fetch=+refs/heads/*:refs/remotes/origin/*
branch.master.remote=origin
branch.master.merge=refs/heads/master&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;(On a side note, I am not sure I remember putting &lt;code class=&quot;language-text&quot;&gt;alias.hist&lt;/code&gt; in my git config, but I find it to be wickedly useful.)&lt;/p&gt;
&lt;p&gt;Setting a new remote is as easy as:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ git remote add new_destination git@github.com:otheruser/thorfiles.git&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Standing back to admire the results:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ git config --list
push.default=nothing
alias.hist=log --pretty=format:&quot;%h %ad | %s%d [%an]&quot; --graph --date=short
user.name=Katie Leonard
…
remote.origin.url=git@github.com:keighty/thorfiles.git
remote.origin.fetch=+refs/heads/*:refs/remotes/origin/*
branch.master.remote=origin
branch.master.merge=refs/heads/master
remote.new_destination.url=git@github.com:otheruser/thorfiles.git
remote.new_destination.fetch=+refs/heads/*:refs/remotes/new_destination/*&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Fast-forward through some excellent and brilliant feature work on &lt;code class=&quot;language-text&quot;&gt;my_branch&lt;/code&gt;, and I naturally want to save it for posterity:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ git push origin my_branch
Counting objects: 611, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (263/263), done.
Writing objects: 100% (375/375), 63.40 KiB | 0 bytes/s, done.
Total 375 (delta 280), reused 189 (delta 105)
To git@github.com:keighty/thorfiles.git
 * [new branch]      my_branch -&gt; my_branch&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I can also share it with my friend’s repo, presuming I have write access, and knowing full well he will want to use my new feature:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ git push new_destination my_branch
Counting objects: 611, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (263/263), done.
Writing objects: 100% (375/375), 63.40 KiB | 0 bytes/s, done.
Total 375 (delta 280), reused 189 (delta 105)
To git@github.com:otheruser/thorfiles.git
 * [new branch]      my_branch -&gt; my_branch&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Git is so awesome.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[delay chained transitions]]></title><description><![CDATA[Changing an element using multiple, chained transitions requires a little troubleshooting. You would think that just chaining them one after…]]></description><link>http://katieleonard.ca/blog/2014/2014-03-15-delay-chained-transitions/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2014/2014-03-15-delay-chained-transitions/</guid><pubDate>Sat, 15 Mar 2014 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Changing an element using multiple, chained transitions requires a little troubleshooting. You would think that just chaining them one after another would suffice:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;selection.transition().duration(1500)
    .attr(&quot;cx&quot;,getX)
    .attr(&quot;cy&quot;,getY)
    .attr(&quot;r&quot;, getR)
    .style(&quot;fill&quot;, getColor)
  .transition().duration(1500)
    .attr(&quot;r&quot;, doubleR);&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;But D3 does not wait for one transition to be complete before it begins the next one. Adding a delay will accomplish the desired transition chaining:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;selection.transition().duration(1500)
    .attr(&quot;cx&quot;,getX)
    .attr(&quot;cy&quot;,getY)
    .attr(&quot;r&quot;, getR)
    .style(&quot;fill&quot;, getColor)
  .transition().delay(1700).duration(1500)
    .attr(&quot;r&quot;, doubleR);&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div id=&quot;showme&quot;&gt;
&lt;style&gt;
.axis path,
.axis line {
    fill: none;
    stroke: black;
    shape-rendering: crispEdges;
}
&lt;p&gt;.axis text {
font-family: sans-serif;
font-size: 11px;
}
&lt;/style&gt;&lt;/p&gt;
&lt;script src=&quot;https://mbostock.github.com/d3/d3.v2.min.js&quot;&gt;&lt;/script&gt;
&lt;script&gt;

var width = 500,
    height = 500,
    margin = 50,
    data,
    dataFromCsv;

var scaleX=d3.scale.linear().domain([0,10]).range([margin,width-margin]);
var scaleY=d3.scale.linear().domain([0,10]).range([height-margin,margin]);

var svg=d3.select(&quot;#showme&quot;).append(&quot;svg&quot;)
      .attr(&quot;width&quot;,width)
      .attr(&quot;height&quot;,height);

function drawAxes() {
  var xAxis = d3.svg.axis()
    .scale(scaleX)
    .orient(&quot;bottom&quot;)
    .ticks(5)
    .tickSubdivide(1)
    .tickPadding(10)
    .tickFormat(function(d) { return d + &quot; ticks&quot;});

  var yAxis = d3.svg.axis()
    .scale(scaleY)
    .orient(&quot;left&quot;);

  svg.append(&quot;g&quot;)
    .attr(&quot;class&quot;, &quot;axis&quot;)
    .attr(&quot;transform&quot;, &quot;translate(0,&quot; + (height - margin) + &quot;)&quot;)
    .call(xAxis);
  svg.append(&quot;text&quot;)
    .attr(&quot;class&quot;, &quot;x label&quot;)
    .attr(&quot;text-anchor&quot;, &quot;middle&quot;)
    .attr(&quot;x&quot;, width/2)
    .attr(&quot;y&quot;, height)
    .text(&quot;X-value&quot;);

  svg.append(&quot;g&quot;)
    .attr(&quot;class&quot;, &quot;axis&quot;)
    .attr(&quot;transform&quot;, &quot;translate(&quot; + margin + &quot;,0)&quot;)
    .call(yAxis);
  svg.append(&quot;text&quot;)
    .attr(&quot;class&quot;, &quot;y label&quot;)
    .attr(&quot;text-anchor&quot;, &quot;middle&quot;)
    .attr(&quot;x&quot;, -height/2)
    .attr(&quot;y&quot;, 6)
    .attr(&quot;dy&quot;, &quot;.75em&quot;)
    .attr(&quot;transform&quot;, &quot;rotate(-90)&quot;)
    .text(&quot;Y-value&quot;);
}

dataFromCsv = [{ &quot;Color&quot;: &quot;#9467bd&quot;, &quot;X&quot;: 1, &quot;Y&quot;: 8, &quot;Quantity&quot;: 91 },
{ &quot;Color&quot;: &quot;#1f77b4&quot;, &quot;X&quot;: 9, &quot;Y&quot;: 1, &quot;Quantity&quot;: 32 },
{ &quot;Color&quot;: &quot;#1f77b4&quot;, &quot;X&quot;: 3, &quot;Y&quot;: 1, &quot;Quantity&quot;: 67 },
{ &quot;Color&quot;: &quot;#bcbd22&quot;, &quot;X&quot;: 5, &quot;Y&quot;: 5, &quot;Quantity&quot;: 63 },
{ &quot;Color&quot;: &quot;#9467bd&quot;, &quot;X&quot;: 6, &quot;Y&quot;: 6, &quot;Quantity&quot;: 57 },
{ &quot;Color&quot;: &quot;#2ca02c&quot;, &quot;X&quot;: 5, &quot;Y&quot;: 10, &quot;Quantity&quot;: 65 },
{ &quot;Color&quot;: &quot;#d62728&quot;, &quot;X&quot;: 8, &quot;Y&quot;: 2, &quot;Quantity&quot;: 36 },
{ &quot;Color&quot;: &quot;#9467bd&quot;, &quot;X&quot;: 2, &quot;Y&quot;: 8, &quot;Quantity&quot;: 82 },
{ &quot;Color&quot;: &quot;#bcbd22&quot;, &quot;X&quot;: 4, &quot;Y&quot;: 7, &quot;Quantity&quot;: 69 },
{ &quot;Color&quot;: &quot;#9467bd&quot;, &quot;X&quot;: 5, &quot;Y&quot;: 3, &quot;Quantity&quot;: 88 },
{ &quot;Color&quot;: &quot;#d62728&quot;, &quot;X&quot;: 1, &quot;Y&quot;: 5, &quot;Quantity&quot;: 29 },
{ &quot;Color&quot;: &quot;#1f77b4&quot;, &quot;X&quot;: 10, &quot;Y&quot;: 7, &quot;Quantity&quot;: 60 },
{ &quot;Color&quot;: &quot;#2ca02c&quot;, &quot;X&quot;: 8, &quot;Y&quot;: 5, &quot;Quantity&quot;: 56 },
{ &quot;Color&quot;: &quot;#bcbd22&quot;, &quot;X&quot;: 1, &quot;Y&quot;: 6, &quot;Quantity&quot;: 31 },
{ &quot;Color&quot;: &quot;#bcbd22&quot;, &quot;X&quot;: 6, &quot;Y&quot;: 5, &quot;Quantity&quot;: 57 },
{ &quot;Color&quot;: &quot;#d62728&quot;, &quot;X&quot;: 9, &quot;Y&quot;: 6, &quot;Quantity&quot;: 85 },
{ &quot;Color&quot;: &quot;indigo&quot;, &quot;X&quot;: 9, &quot;Y&quot;: 10, &quot;Quantity&quot;: 70 },
{ &quot;Color&quot;: &quot;indigo&quot;, &quot;X&quot;: 9, &quot;Y&quot;: 10, &quot;Quantity&quot;: 31 },
{ &quot;Color&quot;: &quot;#1f77b4&quot;, &quot;X&quot;: 2, &quot;Y&quot;: 4, &quot;Quantity&quot;: 26 },
{ &quot;Color&quot;: &quot;#bcbd22&quot;, &quot;X&quot;: 10, &quot;Y&quot;: 5, &quot;Quantity&quot;: 61 },
{ &quot;Color&quot;: &quot;#2ca02c&quot;, &quot;X&quot;: 4, &quot;Y&quot;: 2, &quot;Quantity&quot;: 64 },
{ &quot;Color&quot;: &quot;#1f77b4&quot;, &quot;X&quot;: 8, &quot;Y&quot;: 9, &quot;Quantity&quot;: 71 }];
function importData() {
  data = d3.nest()
          .key(function(d) { return d.Color; })
          .rollup(aggregateData)
          .entries(dataFromCsv);
  // drawElements();
  setInterval( drawElements, 4000 );
}

/***********************
  Draw circles, bind data, and move elements to final location
***********************/
function drawElements() {
  var selection = svg.selectAll(&quot;circle&quot;).data(data);

  selection.enter()
    .append(&quot;circle&quot;)
    .attr(&quot;cx&quot;,scaleX(0))
    .attr(&quot;cy&quot;,scaleY(0))
    .attr(&quot;r&quot;, 0)

  selection.transition().duration(1500)
      .attr(&quot;cx&quot;,getX)
      .attr(&quot;cy&quot;,getY)
      .attr(&quot;r&quot;, getR)
      .style(&quot;fill&quot;, getColor)
    .transition().delay(1500+200).duration(1500)
      .attr(&quot;r&quot;, doubleR);
}

/***********************
  Helper functions
***********************/
function getX(d)     { return scaleX(d.values.X); }
function getY(d)     { return scaleY(d.values.Y); }
function getR(d)     { return d.values.Quantity / 10; }
function doubleR(d)     { return d.values.Quantity / 5; }
function getColor(d) { return d.key; }
// Use D3 built in array functions to aggregate data
function aggregateData(d) {
  return {
    &quot;X&quot;       : d3.mean(d, function(e) { return +e.X; }),
    &quot;Y&quot;       : d3.median(d, function(e) { return +e.Y; }),
    &quot;Quantity&quot;: d3.max(d, function(e) { return +e.Quantity; })
  };
}

drawAxes();
importData();
&lt;/script&gt;
&lt;/div&gt;</content:encoded></item><item><title><![CDATA[easing does it]]></title><description><![CDATA[With the possible exception of UFOs, things don’t usually switch from being stationary to moving at maximum velocity without an intervening…]]></description><link>http://katieleonard.ca/blog/2014/2014-03-12-easing-does-it/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2014/2014-03-12-easing-does-it/</guid><pubDate>Wed, 12 Mar 2014 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;With the possible exception of UFOs, things don’t usually switch from being stationary to moving at maximum velocity without an intervening period of acceleration or deceleration. Similarly, it can be difficult to track elements on a web page that move from one position to another with no warning, or faster than the human eye can perceive. Enter easing functions: &lt;!--more--&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;”&lt;strong&gt;Easing functions&lt;/strong&gt; specify the rate of change of a parameter over time.” —Robert Penner&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;selection.enter()
  .append(&quot;circle&quot;)
  .attr(&quot;cx&quot;,scaleX(0))
  .attr(&quot;cy&quot;,scaleY(0))
  .attr(&quot;r&quot;, 0);
selection.transition().ease(&quot;cubic-in-out&quot;).duration(1500)
  .attr(&quot;cx&quot;,getX)
  .attr(&quot;cy&quot;,getY)
  .attr(&quot;r&quot;, getR)
  .style(&quot;fill&quot;, getColor);&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The transition will act on the selection in the following ways:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;it will move the element from its starting x position of 0 to the x position defined by &lt;code class=&quot;language-text&quot;&gt;getX()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;it will move the element from its starting y position of 0 to the y position defined by &lt;code class=&quot;language-text&quot;&gt;getY()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;it will increase the element’s radius from 0 to the radius returned from &lt;code class=&quot;language-text&quot;&gt;getR()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;it will gradually change the element’s color using an ordinal color scale, from black to the color returned from &lt;code class=&quot;language-text&quot;&gt;getColor()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;all of this movement will be performed with a “cubic-in-out” easing function&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The cubic-in-out easing function is the standard D3 easing function. The element will increase velocity by a power of 3 until halfway down the path it is destined to trace. It will then decrease velocity by a power of 3 until it reaches its final location. There are many different types of easing functions. Check out the resources for more information, and ask your doctor which easing function is right for you!&lt;/p&gt;
&lt;h3&gt;Resources&lt;/h3&gt;
&lt;p&gt;Robert Penner’s &lt;a href=&quot;http://www.robertpenner.com/easing/&quot;&gt;Easing Functions&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.amazon.com/gp/product/178216216X/ref=as_li_tf_tl?ie=UTF8&amp;#x26;camp=1789&amp;#x26;creative=9325&amp;#x26;creativeASIN=178216216X&amp;#x26;linkCode=as2&amp;#x26;tag=bridgeforpoke-20&quot;&gt;Data Visualization with D3.js Cookbook&lt;/a&gt; (affiliate link)&lt;/p&gt;</content:encoded></item><item><title><![CDATA[git, what have I done?]]></title><description><![CDATA[Git, the superhero of version control, allows you to review all the commands that have modified the HEAD tag in a git repo:  The output for…]]></description><link>http://katieleonard.ca/blog/2014/2014-03-08-git-what-have-i-done/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2014/2014-03-08-git-what-have-i-done/</guid><pubDate>Sat, 08 Mar 2014 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Git, the superhero of version control, allows you to review all the commands that have modified the HEAD tag in a git repo: &lt;code class=&quot;language-text&quot;&gt;git reflog&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;The output for one of my demo apps:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;5075d26 HEAD@{0}: checkout: moving from master to kleonard/add_skyline_background
531c396 HEAD@{1}: pull: fast forward
435f6de HEAD@{2}: commit: Adds logic for running and testing
043e35a HEAD@{3}: commit: Adds logic to process input
5155ba4 HEAD@{4}: commit: Adds input file
a629871 HEAD@{5}: rebase finished: returning to refs/heads/kleonard/create_input_files
a010021 HEAD@{6}: rebase: Add input file
b7cd86a HEAD@{7}: commit: Initial commit arbitrage
5ed00ea HEAD@{8}: commit: Adds launcher
7b2d720 HEAD@{9}: commit: Adds logic to find smallest number of moves
9c0dfce HEAD@{10}: commit: Adds implementation for bin creation&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Hmmm… looks like my commit messages need a little work… Still, it is a great tool for catching up on the changes to a repo (especially if you haven’t touched it in a while), finding out where the bulk of the work is happening, or just reminding yourself what you did yesterday.&lt;/p&gt;
&lt;p&gt;Awesome.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[the value of slow transitions]]></title><description><![CDATA[The Why From Object Constancy by Mike Bostock: Animated transitions are pretty, but they also serve a purpose: they make it easier to follow…]]></description><link>http://katieleonard.ca/blog/2014/2014-03-08-the-value-of-transition/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2014/2014-03-08-the-value-of-transition/</guid><pubDate>Sat, 08 Mar 2014 00:00:00 GMT</pubDate><content:encoded>&lt;h3&gt;The Why&lt;/h3&gt;
&lt;p&gt;From &lt;a href=&quot;http://bost.ocks.org/mike/constancy/&quot;&gt;Object Constancy&lt;/a&gt; by Mike Bostock:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Animated transitions are pretty, but they also serve a purpose: they make it easier to follow the data. This is known as &lt;strong&gt;object constancy&lt;/strong&gt;: a graphical element that represents a particular data point… can be tracked visually through the transition. This lessens the cognitive burden by using &lt;strong&gt;preattentive processing&lt;/strong&gt; of motion rather than sequential scanning of labels.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;(The emphasis is mine)&lt;/p&gt;
&lt;h3&gt;The How&lt;/h3&gt;
&lt;p&gt;Object constancy is achieved through object identity: the data is bound to it’s object by a shared unique identifier. This allows D3 to reuse the object when the data set is updated. Object identity is achieved by passing a key function to the data() method at the time of data binding:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;var data = [ // &amp;lt;-A
        {id: 0, value: &quot;foo&quot;},
        {id: 1, value: &quot;bar&quot;},
        {id: 2, value: &quot;foo&quot;},
        {id: 3, value: &quot;baz&quot;},
        {id: 4, value: &quot;bar&quot;}
    ];
d3.selectAll(&quot;svg:g&quot;)
    .data(data, function(d){return d.id;});&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</content:encoded></item><item><title><![CDATA[transition with style]]></title><description><![CDATA[Making things zoom across the page is what I used to think javascript was all about, but it wasn’t until I started learning d3 that I found…]]></description><link>http://katieleonard.ca/blog/2014/2014-03-06-transition-with-style/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2014/2014-03-06-transition-with-style/</guid><pubDate>Thu, 06 Mar 2014 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Making things zoom across the page is what I used to think javascript was all about, but it wasn’t until I started learning d3 that I found out how to make it happen.&lt;/p&gt;
&lt;!--more--&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;var body = d3.select(&quot;body&quot;),
    duration = 2000;

body.append(&quot;div&quot;)
        .style(&quot;background-color&quot;, &quot;white&quot;)
        .style(&quot;margin&quot;, &quot;40px&quot;)
        .style(&quot;width&quot;, &quot;200px&quot;)
        .style(&quot;height&quot;, &quot;200px&quot;)
        .style(&quot;border&quot;, &quot;black solid thin&quot;)
    .transition()
    .duration(duration)
        .style(&quot;background-color&quot;, &quot;black&quot;)
        .style(&quot;margin-left&quot;, &quot;600px&quot;)
        .style(&quot;width&quot;, &quot;100px&quot;)
        .style(&quot;height&quot;, &quot;100px&quot;);&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;D3 is smart enough to select an appropriate scale for the property in transition. If a transitioning element is not given an explicit starting point, D3 will use the computed style. If the end value is missing, the property will be treated as a constant. In the example above, the border stays the same, as do the top and bottom margins. The only properties that change are the ones specified below the transition().&lt;/p&gt;
&lt;p&gt;Awesome.&lt;/p&gt;
&lt;h3&gt;Resources&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;http://www.amazon.com/gp/product/178216216X/ref=as_li_tf_tl?ie=UTF8&amp;#x26;camp=1789&amp;#x26;creative=9325&amp;#x26;creativeASIN=178216216X&amp;#x26;linkCode=as2&amp;#x26;tag=bridgeforpoke-20&quot;&gt;Data Visualization with D3.js Cookbook&lt;/a&gt; (affiliate link)&lt;/p&gt;</content:encoded></item><item><title><![CDATA[fun with ticks]]></title><description><![CDATA[D3 has an awesome tick library, which makes it easy to customize an axis. I have not found any evidence of a built in function to customize…]]></description><link>http://katieleonard.ca/blog/2014/2014-03-05-scales-and-ticks/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2014/2014-03-05-scales-and-ticks/</guid><pubDate>Wed, 05 Mar 2014 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;D3 has an awesome tick library, which makes it easy to customize an axis. I have not found any evidence of a built in function to customize tick rendering depending on if it is a major or a minor tick. One way to get around that is to render two axes, and only label one&lt;!--more--&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;var scaleX=d3.scale.linear().domain([0,10]).range([margin,width-margin]);

var svg=d3.select(&quot;body&quot;).append(&quot;svg&quot;)
      .attr(&quot;width&quot;,width)
      .attr(&quot;height&quot;,height);

var xAxis = d3.svg.axis()
  .scale(scaleX)
  .orient(&quot;bottom&quot;)
  .ticks(5)
  .tickSubdivide(5)
  .tickPadding(10)
  .tickFormat(function(d) { return d + &quot; ticks&quot;});

var x2Axis = d3.svg.axis()
  .scale(scaleX)
  .orient(&quot;bottom&quot;)
  .ticks(5)
  .tickSize(14)
  .tickFormat(&quot;&quot;);

svg.append(&quot;g&quot;)
  .attr(&quot;class&quot;, &quot;axis&quot;)
  .attr(&quot;transform&quot;, &quot;translate(0,&quot; + (margin) + &quot;)&quot;)
  .call(xAxis);

svg.append(&quot;g&quot;)
  .attr(&quot;class&quot;, &quot;axis&quot;)
  .attr(&quot;transform&quot;, &quot;translate(0,&quot; + (margin) + &quot;)&quot;)
  .call(x2Axis);&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;TADA&lt;/h3&gt;
&lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 459px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/ae8aee717560e656e3fcc7db040bff3c/48711/post_d3_scale_major_ticks.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 15.18987341772152%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAADCAIAAAAcOLh5AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAfElEQVQI1y3Oyw7DIAxEUf7/HxsplC4aYQIKxLwGV6HclXU0CysRGWO0GYDee60V6AAe6gufE1jY2hhDRNSdbmPMdV1EpPfdWhtCOL6H1jrMttdmLcUYzdN7Lu3HGM5ZMbNzTkQA+PMspYgIM3vv/08RUZ6YUlwIOOfSzT/kn6xcCdCiEgAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;post d3 scale major ticks&quot; title=&quot;post d3 scale major ticks&quot; src=&quot;/static/ae8aee717560e656e3fcc7db040bff3c/48711/post_d3_scale_major_ticks.png&quot; srcset=&quot;/static/ae8aee717560e656e3fcc7db040bff3c/c26ae/post_d3_scale_major_ticks.png 158w,
/static/ae8aee717560e656e3fcc7db040bff3c/6bdcf/post_d3_scale_major_ticks.png 315w,
/static/ae8aee717560e656e3fcc7db040bff3c/48711/post_d3_scale_major_ticks.png 459w&quot; sizes=&quot;(max-width: 459px) 100vw, 459px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
&lt;h3&gt;More fun with ticks&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;orient()&lt;/strong&gt;: set which side of the axis will be ticked and labeled&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ticks()&lt;/strong&gt;: set the number of major ticks&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;tickSubdivide()&lt;/strong&gt;: set the number of minor ticks&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;tickPadding()&lt;/strong&gt;: set the distance between the ticks and their label&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;tickFormat()&lt;/strong&gt;: set the units to appear after the label on the major ticks&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;tickSize()&lt;/strong&gt;: specify one arg for inner ticks, another argument for outer ticks, or use outerTickSize() or innerTickSize() to specify one or the other. Outer ticks are at the ends of the scales.&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[a technique for producing ideas]]></title><description><![CDATA[A Technique for Producing Ideas by James Webb Young (1965) Young proposes that all ideas are the result of five identifiable stages of…]]></description><link>http://katieleonard.ca/blog/2014/2014-03-04-a-technique-for-producing-ideas/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2014/2014-03-04-a-technique-for-producing-ideas/</guid><pubDate>Tue, 04 Mar 2014 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;http://www.amazon.com/gp/product/B001C34HUS/ref=as_li_tf_tl?ie=UTF8&amp;#x26;camp=1789&amp;#x26;creative=9325&amp;#x26;creativeASIN=B001C34HUS&amp;#x26;linkCode=as2&amp;#x26;tag=bridgeforpoke-20&quot;&gt;A Technique for Producing Ideas&lt;/a&gt; by James Webb Young (1965)&lt;/p&gt;
&lt;p&gt;Young proposes that all ideas are the result of five identifiable stages of rumination, whether they are followed consciously or not:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Gather information, and not just what is specific to your problem domain. Novelty comes from mashing seemingly unrelated concepts together.&lt;/li&gt;
&lt;li&gt;Review the information — collate your information in some fashion and go over it. A lot.&lt;/li&gt;
&lt;li&gt;Do something else. Get distracted from whatever problem you are trying to solve.&lt;/li&gt;
&lt;li&gt;“Eureka! I have it!”&lt;/li&gt;
&lt;li&gt;Refine your idea — first drafts are never perfect, so keep polishing.&lt;/li&gt;
&lt;/ol&gt;</content:encoded></item><item><title><![CDATA[ordinal scale]]></title><link>http://katieleonard.ca/blog/2014/2014-03-04-ordinal-scale/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2014/2014-03-04-ordinal-scale/</guid><pubDate>Tue, 04 Mar 2014 00:00:00 GMT</pubDate><content:encoded>&lt;!--more--&gt;</content:encoded></item><item><title><![CDATA[d3 nests and rollups]]></title><description><![CDATA[D3 provides powerful functions for manipulating raw data sets, including csv(), nest(), and rollup(). I generated a hundred rows of test…]]></description><link>http://katieleonard.ca/blog/2014/2014-03-04-d3-nests-and-rollups/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2014/2014-03-04-d3-nests-and-rollups/</guid><pubDate>Tue, 04 Mar 2014 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;D3 provides powerful functions for manipulating raw data sets, including csv(), nest(), and rollup().&lt;/p&gt;
&lt;!--more--&gt;
&lt;p&gt;I generated a hundred rows of test_data.csv using &lt;a href=&quot;https://www.generatedata.com/#about&quot;&gt;generatedata.com&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;Colors,X,Y,Quantity
violet,1,8,91
blue,9,1,32
blue,3,1,67
yellow,5,5,63
violet,6,6,57
green,5,10,65
red,8,2,36
...&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The basic properties are a Color (one of blue, yellow, violet, green, and red), an X-value (between 1 and 10), a Y-value (also between 1 and 10), and a Quantity value (between 1 and 100).&lt;/p&gt;
&lt;h3&gt;csv()&lt;/h3&gt;
&lt;p&gt;You can import a raw, comma-delimited data file, and bind the data directly to an svg.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;d3.csv(&quot;test_data.csv&quot;, function(csv) {

  svg.selectAll(&quot;circle&quot;).data(csv).enter()
    .append(&quot;circle&quot;)
    .attr(&quot;cx&quot;,getX)
    .attr(&quot;cy&quot;,getY)
    .attr(&quot;r&quot;, getR)
    .style(&quot;fill&quot;, getColor);
})&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 457px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/bbd0cdc81d35d8aeb631dab9ccec0bb8/34f1d/post_d3_csv_data.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 101.8987341772152%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAIAAAAC64paAAAACXBIWXMAAAsTAAALEwEAmpwYAAABmElEQVQ4y5VU7W7bMAz0+79Qn6HYjwBDWxTbj6JF0qHpEkeyJMoyyRskJY7iNcF2MGgREj90R7vDP0M1Py26vu/HcVycExUAq1+rjd2UMJ3tz2/vHy+H6nah4Lh3mZiFa5YKItgBEBE+nuustc65OfG1hgG8vWG1Ors5eBgGH71uVazwJ2uqOwro7fvnYOdcGIOshXvmd9ZR/4MwX9C0Xe0GeGzcJZ6fESOuETYAu2PwIpwZqrsdeEJnjPE+AKNq/LIIf0KnKmBh/u4OT0/VrW2HXJinvwIdkFQclAGMPAaOud2UyhaXyiEgJY1t5SrvI/Ab+KGa77X129fD64nq7wB1RDTfeVrUltt6FZ3diW2ipTot4UUpbbeyzpdSnc+nl8Rbvq7XQqp5espSehEvt9o2xrSzXe3arh8+Hs4Zq3UO1rbD3cUY28oiMAcoZJLpq4HWdkiX40mE+/uLT2eBEDDzmtne7/e1fghERCmVFx391p4Q6v8jB1trY4ze+7IYjTGRaBhcXsRojCEKzrnBuSqNc4M5HJjlD0C0mdueYxx9AAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;post d3 csv data&quot; title=&quot;post d3 csv data&quot; src=&quot;/static/bbd0cdc81d35d8aeb631dab9ccec0bb8/34f1d/post_d3_csv_data.png&quot; srcset=&quot;/static/bbd0cdc81d35d8aeb631dab9ccec0bb8/c26ae/post_d3_csv_data.png 158w,
/static/bbd0cdc81d35d8aeb631dab9ccec0bb8/6bdcf/post_d3_csv_data.png 315w,
/static/bbd0cdc81d35d8aeb631dab9ccec0bb8/34f1d/post_d3_csv_data.png 457w&quot; sizes=&quot;(max-width: 457px) 100vw, 457px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
&lt;h3&gt;nest() and rollup()&lt;/h3&gt;
&lt;p&gt;You can also aggregate data on any property — just tell D3 which one, and use any of D3’s handy utility functions (mean, median, sum, min/max, quantile, etc) to return the aggregate data you want to display. For example, I want to plot the average data for each color. I tell my D3 selection to nest the data on the color key. Then I tell the rollup function to take the average for each property of the data. Pass the new data to the svg instead of the csv, and voila&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;d3.csv(&quot;test_data.csv&quot;,function(csv) {
  data = d3.nest()
          .key(function(d) { return d.Colors; })
          .rollup( function(d) {
            return {
              &quot;X&quot;: d3.mean(d, function(e) { return +e.X; }),
              &quot;Y&quot;: d3.mean(d, function(e) { return +e.Y; }),
              &quot;Quantity&quot;: d3.mean(d, function(e) { return +e.Quantity; })
            };
          })
          .entries(csv);

  svg.selectAll(&quot;circle&quot;).data(data).enter()
    .append(&quot;circle&quot;)
    .attr(&quot;cx&quot;,getX)
    .attr(&quot;cy&quot;,getY)
    .attr(&quot;r&quot;, getR)
    .style(&quot;fill&quot;, getColor);

})&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 445px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/13975a1c085d944c2bd82794d0896218/e66bf/post_d3_rollupdata_image.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 104.43037974683544%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAVCAIAAADJt1n/AAAACXBIWXMAAAsTAAALEwEAmpwYAAAA+klEQVQ4y6WSQW/DIAyF+/9/2K6TJk3aaVKlScsOE2BsYwy4U0IPa5SkacoBYdDHg+d3ujwxTgAgIvuB1uzn7FuzERaRGON+2MwoiNkEM7P3vu8+/OyccwjhIExIzrmDcK31oT/fwCKy8Oe2sFqGAeDW0It+qGU7qGxqvdT69vr9UuvyRWOrNgwzC1Rw7Q2nUsqGYZM6f717ztdqppycWwlJ32L0n7/almBV7SE50qqU0t14rh2NyvNW7VfmxM4fjee223fgpwxjTsMwEBFMI8b4fw4h9PXsCACyyNWwWotIRsRSChGLCCFlVUTUnCNSSlxrBQBVjYg91H8+odt8bSsCyAAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;post d3 rollupdata image&quot; title=&quot;post d3 rollupdata image&quot; src=&quot;/static/13975a1c085d944c2bd82794d0896218/e66bf/post_d3_rollupdata_image.png&quot; srcset=&quot;/static/13975a1c085d944c2bd82794d0896218/c26ae/post_d3_rollupdata_image.png 158w,
/static/13975a1c085d944c2bd82794d0896218/6bdcf/post_d3_rollupdata_image.png 315w,
/static/13975a1c085d944c2bd82794d0896218/e66bf/post_d3_rollupdata_image.png 445w&quot; sizes=&quot;(max-width: 445px) 100vw, 445px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
&lt;p&gt;D3 is so awesome.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[scaling d3]]></title><description><![CDATA[Add scales to a d3 plot in three easy steps: 1. Define the scale 2. Draw the scale 3. Apply the scale to your data Awesome.]]></description><link>http://katieleonard.ca/blog/2014/2014-03-03-d3-scaling/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2014/2014-03-03-d3-scaling/</guid><pubDate>Mon, 03 Mar 2014 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Add scales to a d3 plot in three easy steps:&lt;/p&gt;
&lt;h3&gt;1. Define the scale&lt;/h3&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Image dimensions&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; width &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;500&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    height &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;500&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    margin &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;50&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; scaleX&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;d3&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;scale&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;linear&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;domain&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;margin&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; width&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;margin&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; scaleY&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;d3&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;scale&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;linear&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;domain&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;height&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;margin&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; margin&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;2. Draw the scale&lt;/h3&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Image container&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; svg&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;d3&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;select&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;body&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;svg&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;width&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;width&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;height&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;height&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Axis definition&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; xAxis &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; d3&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;svg&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;axis&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;scale&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;scaleX&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;orient&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;bottom&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; yAxis &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; d3&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;svg&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;axis&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;scale&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;scaleY&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;orient&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;left&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Axis graphics&lt;/span&gt;
svg&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;g&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;class&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;axis&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;transform&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;translate(0,&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;height &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; margin&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;)&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;xAxis&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

svg&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;g&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;class&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;axis&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;transform&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;translate(&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; margin &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;,0)&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;yAxis&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;3. Apply the scale to your data&lt;/h3&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;d3&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;csv&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;test_data.csv&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;csv&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

  svg&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;selectAll&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;circle&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;csv&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;enter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;circle&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;cx&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;getX&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;cy&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;getY&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;r&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; getR&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;style&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;fill&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; getColor&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// Apply scale to the x value&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getX&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;scaleX&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;d&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;X&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;//Apply scale to the y value&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getY&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;scaleY&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;d&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Y&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getR&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; d&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Quantity &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getColor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; d&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Colors&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Awesome.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[javascript dates]]></title><description><![CDATA[Javascript Date objects have zero indexed months but not dates. Wat? Resources Javascript strftime]]></description><link>http://katieleonard.ca/blog/2014/2014-03-01-javascript-dates/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2014/2014-03-01-javascript-dates/</guid><pubDate>Sat, 01 Mar 2014 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Javascript Date objects have zero indexed months but not dates.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;&gt; (new Date(2014, 0, 1)).strftime(&quot;%b %d, %Y&quot;)
&quot;Jan 1, 2014&quot;
&gt; (new Date(2013, 11, 31)).strftime(&quot;%b %d, %Y&quot;)
&quot;Dec 31, 2013&quot;
&gt; (new Date(2014, 0, 0)).strftime(&quot;%b %d, %Y&quot;)
&quot;Dec 31, 2013&quot;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Wat?&lt;/p&gt;
&lt;!--more--&gt;
&lt;h3&gt;Resources&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;http://tech.bluesmoon.info/2008/04/strftime-in-javascript.html&quot;&gt;Javascript strftime&lt;/a&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[binding functions as data]]></title><description><![CDATA[Primitives and object literals are not the only things you can bind to a D3 visualization. After all, aren’t javascript functions objects as…]]></description><link>http://katieleonard.ca/blog/2014/2014-02-27-binding-functions-as-data/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2014/2014-02-27-binding-functions-as-data/</guid><pubDate>Thu, 27 Feb 2014 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Primitives and object literals are not the only things you can bind to a D3 visualization. After all, aren’t javascript functions objects as well?&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; data &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;next&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;15&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; x&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;x &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;newData&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; data&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;push&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;next&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; data&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; selection &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; d3&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;select&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;#container&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
                  &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;selectAll&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;div&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
                  &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;newData&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
                  &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;select&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;#span&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
                    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;d&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; i&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;If you provide a function to the data function, D3 will simply invoke the function and use the returned value as a parameter of the data function.&lt;/p&gt;
&lt;h3&gt;Resources&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;http://www.amazon.com/gp/product/178216216X/ref=as_li_tf_tl?ie=UTF8&amp;#x26;camp=1789&amp;#x26;creative=9325&amp;#x26;creativeASIN=178216216X&amp;#x26;linkCode=as2&amp;#x26;tag=bridgeforpoke-20&quot;&gt;Data Visualization with D3.js Cookbook&lt;/a&gt; (affiliate link)&lt;/p&gt;</content:encoded></item><item><title><![CDATA[d3 array functions]]></title><description><![CDATA[D3 provides utility functions to perform common operations on Javascript arrays: min max extent (range) sum median mean sort quantile bisect]]></description><link>http://katieleonard.ca/blog/2014/2014-02-27-d3-array-functions/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2014/2014-02-27-d3-array-functions/</guid><pubDate>Thu, 27 Feb 2014 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;D3 provides utility functions to perform common operations on Javascript arrays:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;min&lt;/li&gt;
&lt;li&gt;max&lt;/li&gt;
&lt;li&gt;extent (range)&lt;/li&gt;
&lt;li&gt;sum&lt;/li&gt;
&lt;li&gt;median&lt;/li&gt;
&lt;li&gt;mean&lt;/li&gt;
&lt;li&gt;sort&lt;/li&gt;
&lt;li&gt;quantile&lt;/li&gt;
&lt;li&gt;bisect&lt;/li&gt;
&lt;/ul&gt;
&lt;!--more--&gt;</content:encoded></item><item><title><![CDATA[The Neuroscience of Programming]]></title><description><![CDATA[Scientists Begin Looking at Programmers’ Brains: The Neuroscience of Programming from The Huffington Post. A new study provides new evidence…]]></description><link>http://katieleonard.ca/blog/2014/2014-02-27-programming-and-linguistics/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2014/2014-02-27-programming-and-linguistics/</guid><pubDate>Thu, 27 Feb 2014 00:00:00 GMT</pubDate><content:encoded>&lt;h3&gt;&lt;a href=&quot;http://www.huffingtonpost.com/chris-parnin/scientists-begin-looking-_b_4829981.html&quot;&gt;Scientists Begin Looking at Programmers’ Brains: The Neuroscience of Programming&lt;/a&gt; from The Huffington Post.&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;A new study provides new evidence that programmers are using language regions of the brain when understanding code and found little activation in other regions of the brain devoted to mathematical thinking.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;Each programming language you learn requires expressing abstract concepts with a different syntax — and in the case of punctuation (~&gt;, =&gt;, :, {}, [], etc) an augmented alphabet. How is a programming language NOT like linguistics?&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;Besides a mathematical inclination, an exceptionally good mastery of one’s native tongue is the most vital asset of a competent programmer. —Djikstra&lt;/p&gt;
&lt;/blockquote&gt;</content:encoded></item><item><title><![CDATA[string conversion in javascript]]></title><description><![CDATA[Almost every day, javascript blows my mind. Today I discovered that you can convert a string to a number simply by prepending a +: Awesome.]]></description><link>http://katieleonard.ca/blog/2014/2014-02-28-to-i-in-javascript/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2014/2014-02-28-to-i-in-javascript/</guid><pubDate>Thu, 27 Feb 2014 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Almost every day, javascript blows my mind. Today I discovered that you can convert a string to a number simply by prepending a +:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;&gt; typeof(+&quot;this is a string&quot;)
&quot;number&quot;
&gt; typeof(+&quot;100&quot;)
&quot;number&quot;
&gt; +&quot;100&quot; + 50
150&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Awesome.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[implied functions applied]]></title><description><![CDATA[When binding a primitive datum to a node in a D3 visualization, the callback function can be implicitly called on the datum without the…]]></description><link>http://katieleonard.ca/blog/2014/2014-02-26-implied-functions-applied/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2014/2014-02-26-implied-functions-applied/</guid><pubDate>Wed, 26 Feb 2014 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;When binding a primitive datum to a node in a D3 visualization, the callback function can be implicitly called on the datum without the typical verbosity&lt;!--more--&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;svg&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;selectAll&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;circle&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;32&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;57&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;112&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;293&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;enter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;circle&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;cy&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;90&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;cx&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; String&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;r&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; Math&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;sqrt&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In line 5, String() is performed on the data element, as is Math.sqrt in line 6, with the same result as:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;svg.selectAll(&quot;circle&quot;)
    .data([32, 57, 112, 293])
  .enter().append(&quot;circle&quot;)
    .attr(&quot;cy&quot;, 90)
    .attr(&quot;cx&quot;, function(d) {
      return String(d);
    })
    .attr(&quot;r&quot;, function(d) {
      return Math.sqrt(d);
    });&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;… but better.&lt;/p&gt;
&lt;p&gt;Awesome.&lt;/p&gt;
&lt;h3&gt;Resources&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;http://mbostock.github.io/d3/tutorial/circle.html&quot;&gt;Three Little Circles D3 Tutorial&lt;/a&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[visualize with purpose]]></title><description><![CDATA[Information visualization (insight, understanding, and discovery) and information art (aesthetics) differ in their context, audience, and…]]></description><link>http://katieleonard.ca/blog/2014/2014-02-26-why-visualize/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2014/2014-02-26-why-visualize/</guid><pubDate>Wed, 26 Feb 2014 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Information visualization (insight, understanding, and discovery) and information art (aesthetics) differ in their context, audience, and goals. In my exploration of D3 I came across an &lt;a href=&quot;http://www.visualcomplexity.com/vc/blog/?p=644&quot;&gt;Information Visualization Manifesto&lt;/a&gt; by Manuel Lima, and this is what I have learned&lt;!--more--&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Form follows function&lt;/strong&gt;: keep your problem domain in mind when assembling a visualization.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Question&lt;/strong&gt;: Drive your work through questions and curiosity.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Interactivity&lt;/strong&gt; is key.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Sources&lt;/strong&gt;: Provide access to the raw data if possible.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Narrative&lt;/strong&gt;: Tell a story with your data.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Aesthetics&lt;/strong&gt; Are a consequence of visualization, not a goal.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Relevancy&lt;/strong&gt;: What is the context? What patterns are discernable?&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Time&lt;/strong&gt;: Consider time when your data is affected by it.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Knowledge&lt;/strong&gt;: Bring new understanding and insight.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Ease up&lt;/strong&gt;: Not everything can or should be visualized. Be deliberate and add to information, don’t obfuscate with unnecessary visualizations.&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[enter update exit]]></title><description><![CDATA[D3 is a data visualization tool that uses method chaining to produce big pictures with little code. The selection library performs a full…]]></description><link>http://katieleonard.ca/blog/2014/2014-02-25-enter-update-exit/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2014/2014-02-25-enter-update-exit/</guid><pubDate>Tue, 25 Feb 2014 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;D3 is a data visualization tool that uses method chaining to produce big pictures with little code. The selection library performs a full Outer Join between the data (D) and the visual elements (V), and the enter-update-exit pattern performs work on subsets of this join&lt;!--more--&gt;:&lt;/p&gt;
&lt;h3&gt;UPDATE: Inner Join (D union V)&lt;/h3&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;selection.data(data_points)&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;data() binds data_points to the html or svg elements returned by the selection and returns the data not visualized.&lt;/p&gt;
&lt;h3&gt;ENTER: Left excluding join (D/V)&lt;/h3&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;selection.data(data_points).enter()&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;enter() returns data_points that are not yet represented visually by html or svg. Chain .append() to add a new element to the page.&lt;/p&gt;
&lt;h3&gt;EXIT: Right excluding join (V/D)&lt;/h3&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;selection.data(data_points).exit()&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;exit() returns html or svg elements that no longer have data associated with them. Chain .remove() to eliminate them, or .translate() to make them slide off the page.&lt;/p&gt;
&lt;h3&gt;Resources&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;http://www.amazon.com/gp/product/178216216X/ref=as_li_tf_tl?ie=UTF8&amp;#x26;camp=1789&amp;#x26;creative=9325&amp;#x26;creativeASIN=178216216X&amp;#x26;linkCode=as2&amp;#x26;tag=bridgeforpoke-20&quot;&gt;Data Visualization with D3.js Cookbook&lt;/a&gt; (affiliate link)&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.codeproject.com/Articles/33052/Visual-Representation-of-SQL-Joins&quot;&gt;Visual Representation of SQL Joins&lt;/a&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[d3 is selective]]></title><description><![CDATA[D3 uses the W3C standard selector library, and selection modifiers work on both single and multiple element selections, and will…]]></description><link>http://katieleonard.ca/blog/2014/2014-02-21-d3-is-selective/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2014/2014-02-21-d3-is-selective/</guid><pubDate>Fri, 21 Feb 2014 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;D3 uses the W3C standard selector library, and selection modifiers work on both single and multiple element selections, and will automatically apply the modifier iteratively over the entire collection, which makes your code simpler and easier to maintain.&lt;/p&gt;
&lt;!--more--&gt;
&lt;h4&gt;Selection modifiers&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;d3.select(‘p’).text()&lt;/strong&gt;     : retrieve or modify text&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;d3.select(‘p’).attr()&lt;/strong&gt;     : retrieve or modify a given attribute&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;d3.select(‘p’).classed()&lt;/strong&gt;  : retrieve or modify css classes&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;d3.select(‘p’).style()&lt;/strong&gt;    : retrieve or modify styles&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;d3.select(‘p’).html()&lt;/strong&gt;     : retrieve or modify a selections inner html (like text but with tags)&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;d3.selectAll(&apos;div&apos;)
            .attr(&quot;class&quot;, &quot;alert&quot;)
            .each(function(d, i) {
              d3.select(this).append(&quot;h1&quot;).text(i);
            });&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Selections are essentially arrays with some extra variables baked in. The &lt;code class=&quot;language-text&quot;&gt;.each&lt;/code&gt; call on line 3 treats the selected elements as an array, and performs a function on each one. The extra variables provided to the iterator function for free are: the data bound to the element (d), the index of the element, and the element itself (this).&lt;/p&gt;
&lt;p&gt;Awesome&lt;/p&gt;</content:encoded></item><item><title><![CDATA[functional arguing]]></title><description><![CDATA[The  variable is a hidden parameter in javascript functions that contains all the arguments for the invocation in a pseudo-array (ie: it…]]></description><link>http://katieleonard.ca/blog/2014/2014-02-20-functional-arguing/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2014/2014-02-20-functional-arguing/</guid><pubDate>Thu, 20 Feb 2014 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;The &lt;code class=&quot;language-text&quot;&gt;arguments&lt;/code&gt; variable is a hidden parameter in javascript functions that contains all the arguments for the invocation in a pseudo-array (ie: it does not have array functions other than length and indexing).&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;instance&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function-variable function&quot;&gt;headline&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;h&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;arguments&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; headline&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  headline &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; h&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; instance&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Even though the function specifically calls for an argument (&lt;code class=&quot;language-text&quot;&gt;h&lt;/code&gt;), it can still be called without one. This construction has a ruby equivalent, &lt;code class=&quot;language-text&quot;&gt;attr_accessor :headline&lt;/code&gt;, which behaves as a getter and a setter, depending on the arguments provided (none, or &lt;code class=&quot;language-text&quot;&gt;headline = new_value&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;This “variable-parameter” function design is what enables method chaining. When the function is called as a getter it returns a string, but when it is called as a setter it returns the invoking object, passing itself along to the next method:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; widget &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;SimpleWidget&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;#6439ed&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;headline&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;SimpleWidget&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;This is a simple widget&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;render&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;!--more--&gt;
&lt;h3&gt;Resources&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;http://www.amazon.com/gp/product/178216216X/ref=as_li_tf_tl?ie=UTF8&amp;#x26;camp=1789&amp;#x26;creative=9325&amp;#x26;creativeASIN=178216216X&amp;#x26;linkCode=as2&amp;#x26;tag=bridgeforpoke-20&quot;&gt;Data Visualization with D3.js Cookbook&lt;/a&gt; (affiliate link)&lt;/p&gt;</content:encoded></item><item><title><![CDATA[how to live on 24 hours a day]]></title><description><![CDATA[How to Live on 24 Hours a Day, by Arnold Bennett (published in 1910) Arnold Bennett’s recommendations for leading a full and happy life…]]></description><link>http://katieleonard.ca/blog/2014/2014-02-17-how-to-live-on-24-hours-a-day/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2014/2014-02-17-how-to-live-on-24-hours-a-day/</guid><pubDate>Mon, 17 Feb 2014 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;http://www.gutenberg.org/files/2274/2274-h/2274-h.htm&quot;&gt;How to Live on 24 Hours a Day&lt;/a&gt;, by Arnold Bennett (published in 1910)&lt;/p&gt;
&lt;h3&gt;Arnold Bennett’s recommendations for leading a full and happy life:&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Wake up earlier&lt;/li&gt;
&lt;li&gt;Practice concentrating your mind on a single task.&lt;/li&gt;
&lt;li&gt;Don’t try to change too much too quickly.&lt;/li&gt;
&lt;li&gt;Spend time each day reflecting on how closely your life aligns with your principles.&lt;/li&gt;
&lt;li&gt;Study the performing arts.&lt;/li&gt;
&lt;li&gt;Read poetry.&lt;/li&gt;
&lt;li&gt;Failing that, read anything except novels, and think about what you read.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Don’t be smug about it.&lt;/p&gt;
&lt;!--more--&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I was surprised to learn that much of the ennui of modern life turns out not to be particularly modern after all. In this often sarcastic essay, Bennett shares his recipe for maximizing “the full use of one’s time to the great end of living (as distinguished from vegetating).”&lt;/p&gt;
&lt;h3&gt;Wake up earlier&lt;/h3&gt;
&lt;p&gt;In the preface he disposes of the most common excuse for not improving oneself — I just don’t have enough time. The solution is simple:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Employ your engines in something beyond [your routine] before, and not after, you employ them on the [routine] itself. Briefly, get up earlier in the morning… Most people sleep themselves stupid.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This call to action comes before he even outlines his ideas for how you should spend your reclaimed time. Bennett asks the reader whether they have not ever said to themselves “I would love to do such-and-such if only I had the time,” or “When such-and-such is over I will have time to address this-and-that?” We all have the wish to accomplish something beyond our routine, and it will give us no peace (but an awful lot of guilt) until we have done some small thing towards the pursuit of that goal.&lt;/p&gt;
&lt;p&gt;Time is unstealable, and is measured out to you a moment at a time without regard to whether you use it wisely, squander it, or deserve it. No amount of birthright, money or genius will increase your allotment. Why spend it sleeping?&lt;/p&gt;
&lt;h3&gt;Practice concentrating your mind on a single task.&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;You practice physical exercises for a mere ten minutes morning and evening, and yet you are not astonished when your physical health and strength are beneficially affected every hour of the day, and your whole physical outlook changed. Why should you be astonished that an average of over an hour a day given to the mind should permanently and completely enliven the whole activity of the mind?”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;My mind wanders constantly, even though I have read so much about willpower and meditation. Disciplining the mind has to be the difficulty Bennett warned us of, but he claims that “mind control is the first element of a full existence:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Nothing whatever happens to us outside our own brain; since nothing hurts us or gives us pleasure except within the brain, the supreme importance of being able to control what goes on in that mysterious brain is patent.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;Don’t try to take on too much too quickly&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;Beware of undertaking too much at the start. Be content with quite a little. Allow for accidents. Allow for human nature, especially your own.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;At New Year’s time we make resolutions to eat healthier and exercise more, to spend more time with our families and to watch less TV. These are all laudable goals, but they mostly go out the window before the last day of January. Bennett’s advice - “let the pace of the first lap be even absurdly slow, but let it be as regular as possible.” Slow and steady wins the race.&lt;/p&gt;
&lt;h3&gt;Spend time each day reflecting on how closely your life aligns with your principles.&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;All martyrs are happy, because their conduct and their principles agree. [Perform a] daily, candid, honest examination of what one has recently done, and what one is about to do — of a steady looking at one’s self in the face (disconcerting though the sight may be).&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;Study the performing arts.&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;Reading literature is not the only pursuit that will expand your appreciation of the finer things in life. If you enjoy music, pick up a book on how to appreciate music. Then, the next time you found yourself at a concert “you would live [there], whereas previously you had merely existed there in a state of beatific coma, like a baby gazing at a bright object.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;Read poetry&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;A good novel rushes you forward like a skiff down a stream, and you arrive at the end, perhaps breathless, but unexhausted. The best novels involve the least strain. Now in the cultivation of the mind one of the most important factors is precisely the feeling of strain, of difficulty, of a task which one part of you is anxious to achieve and another part of you is anxious to shirk; and that feeling cannot be got in facing a novel. Imaginative poetry produces greater mental strain than a novel.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Bennett has two suggestions beginning a study of any kind: the first is to define the direction and scope of your efforts, the second suggestion is to think as well as to read.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Unless you give at least forty-five minutes to careful, fatiguing reflection (it is an awful bore at first) upon what you are reading, your ninety minutes of a night are chiefly wasted. This means that your pace will be slow.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;Don’t be smug about it&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;It is easy to begin judging people who don’t follow the same program of rigorous mind expansion as you have:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Unconsciously to become a prig is an easy and a fatal thing.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;It is easy to go overboard:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;A programme of daily employ is not a religion.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;Don’t get carried away by the list of things to learn, of being gradually more and more obsessed by what one has to do next.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Don’t try to do too much too quickly&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Let the pace of the first lap be even absurdly slow, but let it be as regular as possible.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Study what you are interested in&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;In choosing [what to study,] be guided by nothing whatever but your taste and natural inclination.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;What an awesome find.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[custom asides]]></title><description><![CDATA[I was following a tutorial on how to include a twitter widget in the sidebar of my octopress site and couldn’t figure out why my twitter…]]></description><link>http://katieleonard.ca/blog/2014/2014-02-15-custom-asides/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2014/2014-02-15-custom-asides/</guid><pubDate>Sat, 15 Feb 2014 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I was following a &lt;a href=&quot;http://blog.jmac.org/blog/2013/03/30/putting-twitter-back-into-octopress/&quot;&gt;tutorial&lt;/a&gt; on how to include a twitter widget in the sidebar of my octopress site and couldn’t figure out why my twitter content wouldn’t render. It turns out that custom asides require an internal div. &lt;!--more--&gt;The process:&lt;/p&gt;
&lt;h3&gt;1. Create a twitter timeline widget&lt;/h3&gt;
&lt;p&gt;This was surprisingly easy. Just login to &lt;a href=&quot;https://twitter.com/&quot;&gt;twitter.com&lt;/a&gt; and click the settings icon: &lt;i class=&quot;fa fa-cog fa-2x&quot;&gt;&lt;/i&gt;&lt;/p&gt;
&lt;p&gt;Click “Widgets” on the bottom of the left nav and follow the instructions.&lt;/p&gt;
&lt;p&gt;CAKE WALK.&lt;/p&gt;
&lt;h3&gt;2. Create a custom aside&lt;/h3&gt;
&lt;p&gt;Perhaps it is the tutorial showing its age, but I couldn’t get the content to render as described. I grabbed the widget html and created a file in source/custom/asides:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;html&quot;&gt;&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;section&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;h1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Twitter&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;h1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- paste twitter widget code here --&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;section&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I looked to the other asides for help, and realized that the content had to be anchored to a div of its own:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;html&quot;&gt;&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;section&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;h1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Twitter&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;h1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- paste twitter widget code here --&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;section&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;3. Add the aside to your _config.yml&lt;/h3&gt;
&lt;p&gt; What my _config.yml looks like&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ruby&quot;&gt;&lt;pre class=&quot;language-ruby&quot;&gt;&lt;code class=&quot;language-ruby&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# list each of the sidebar modules you want to include, in the order you want them to appear.&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# To add custom asides, create files in /source/_includes/custom/asides/ and add them to the list like &apos;custom/asides/custom_aside_name.html&apos;&lt;/span&gt;
&lt;span class=&quot;token symbol&quot;&gt;default_asides&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;custom&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;asides&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;contactme&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;html&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; asides&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;recent_posts&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;html&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; asides&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;github&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;html&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; custom&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;asides&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;aboutme&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;html&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; custom&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;asides&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;twitter&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;html&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Awesome.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[for score]]></title><description><![CDATA[The  statement can function as a quick and semantic iterator for looping over object properties. In your console, try Awesome Resources…]]></description><link>http://katieleonard.ca/blog/2014/2014-02-11-for-score/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2014/2014-02-11-for-score/</guid><pubDate>Tue, 11 Feb 2014 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;The &lt;code class=&quot;language-text&quot;&gt;for in&lt;/code&gt; statement can function as a quick and semantic iterator for looping over object properties.&lt;/p&gt;
&lt;p&gt;In your console, try&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; person &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;first_name&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Katie&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;last_name&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Leonard&quot;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; name&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;name &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; person&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;name &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot; : &quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; person&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token literal-property property&quot;&gt;first_name&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Katie
&lt;span class=&quot;token literal-property property&quot;&gt;last_name&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Leonard&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;!--more--&gt;
&lt;p&gt;Awesome&lt;/p&gt;
&lt;h3&gt;Resources&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;http://www.amazon.com/gp/product/0596517742/ref=as_li_tf_tl?ie=UTF8&amp;#x26;camp=1789&amp;#x26;creative=9325&amp;#x26;creativeASIN=0596517742&amp;#x26;linkCode=as2&amp;#x26;tag=bridgeforpoke-20&quot;&gt;JavaScript: The Good Parts&lt;/a&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[the passionate programmer]]></title><description><![CDATA[The Passionate Programmer: Creating a Remarkable Career in Software Development (Pragmatic Life), by Chad Fowler
(affiliate link) This book…]]></description><link>http://katieleonard.ca/blog/2014/2014-02-10-the-passionate-programmer/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2014/2014-02-10-the-passionate-programmer/</guid><pubDate>Mon, 10 Feb 2014 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;http://www.amazon.com/gp/product/B00AYQNR5U/ref=as_li_tf_tl?ie=UTF8&amp;#x26;camp=1789&amp;#x26;creative=9325&amp;#x26;creativeASIN=B00AYQNR5U&amp;#x26;linkCode=as2&amp;#x26;tag=bridgeforpoke-20&quot;&gt;The Passionate Programmer: Creating a Remarkable Career in Software Development&lt;/a&gt; (Pragmatic Life), by Chad Fowler
(affiliate link)&lt;/p&gt;
&lt;p&gt;This book is aptly titled, and an awesome read. It consists of a series of tips — strategies Fowler has employed to build his own remarkable career. The most important tip is one that can’t really be crossed off a list, and that is to build a successful career in software development one must be passionate about software development.&lt;/p&gt;
&lt;h2&gt;Update:&lt;/h2&gt;
&lt;p&gt;Unbeknownst to me when I was finishing this book, but knownst to me now is that there has been a vibrant conversation occurring on the interweb about passion and programming. Check out Avdi Grimm’s latest, &lt;a href=&quot;http://devblog.avdi.org/2014/02/10/the-passion-gospel/&quot;&gt;The Passion Gospel&lt;/a&gt;.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[augmented objects]]></title><description><![CDATA[Because it bears repeating: javascript and ruby have many features in common, including the ability to add functionality to existing objects…]]></description><link>http://katieleonard.ca/blog/2014/2014-02-09-augmented-objects/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2014/2014-02-09-augmented-objects/</guid><pubDate>Sun, 09 Feb 2014 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Because it bears repeating: javascript and ruby have many features in common, including the ability to add functionality to existing objects.&lt;/p&gt;
&lt;!--more--&gt;
&lt;h2&gt;Ruby singleton&lt;/h2&gt;
&lt;p&gt;You can add methods to an instance of a class without affecting any other instances of that class.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; x, y &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;stringA&quot;&lt;/span&gt;, &lt;span class=&quot;token string&quot;&gt;&quot;stringB&quot;&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; def x.baz
&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;   puts &lt;span class=&quot;token string&quot;&gt;&quot;I can haz?&quot;&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; end
&lt;span class=&quot;token comment&quot;&gt;# =&gt; nil&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; x.baz
I can haz?
&lt;span class=&quot;token comment&quot;&gt;# =&gt; nil&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; y.baz
NoMethodError: undefined method &lt;span class=&quot;token variable&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;`&lt;/span&gt;baz&apos; &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;stringB&quot;&lt;/span&gt;:String
  from &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;irb&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;:62
  from /home/katherine/.rvm/rubies/ruby-2.0.0-rc1/bin/irb:12:in &lt;span class=&quot;token variable&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;main&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&apos;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Javascript augmenting&lt;/h2&gt;
&lt;p&gt;You can add methods to an of an Array object without affecting any other array objects.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;&gt; var data1 = [1, 2, 3, 4, 5, 6];
undefined
&gt; var data2 = [2, 4, 6, 8, 10, 12];
undefined
&gt; data1.total = function() { return 21; };
function () { return 21; }
&gt; data1.total();
21
&gt; data2.total()
TypeError: Object [object Array] has no method &apos;total&apos;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</content:encoded></item><item><title><![CDATA[augmented types]]></title><description><![CDATA[Javascript and Ruby have many features in common, including the ability to add functionality to existing objects. Ruby monkeypatching Ruby…]]></description><link>http://katieleonard.ca/blog/2014/2014-02-08-augmented-types/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2014/2014-02-08-augmented-types/</guid><pubDate>Sat, 08 Feb 2014 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Javascript and Ruby have many features in common, including the ability to add functionality to existing objects.&lt;/p&gt;
&lt;!--more--&gt;
&lt;h2&gt;Ruby monkeypatching&lt;/h2&gt;
&lt;p&gt;Ruby allows you to reopen classes to add new functionality. For example, I can reopen the String class to add a new method, “foo()“:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;irb &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; class String
irb &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;   def foo
irb &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;     &lt;span class=&quot;token string&quot;&gt;&quot;I see you!&quot;&lt;/span&gt;
irb &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;   end
irb &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; end
&lt;span class=&quot;token comment&quot;&gt;# =&gt; nil&lt;/span&gt;
irb &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&quot;&lt;/span&gt;.class
&lt;span class=&quot;token comment&quot;&gt;# =&gt; String&lt;/span&gt;
irb &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&quot;&lt;/span&gt;.foo
&lt;span class=&quot;token comment&quot;&gt;# =&gt; &quot;I see you!&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Javascript augmenting&lt;/h2&gt;
&lt;p&gt;Javascript allows you to augment existing objects with additional functionality.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;prototype&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function-variable function&quot;&gt;foo&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;I see you!&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;I see you!&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;typeof&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token string&quot;&gt;&quot;string&quot;&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token string&quot;&gt;&quot;I see you!&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</content:encoded></item><item><title><![CDATA[global abatement]]></title><description><![CDATA[or, What the heck is global abatement? tldr: Global variables are code smells. Declaring variables inside an application-level function…]]></description><link>http://katieleonard.ca/blog/2014/2014-02-07-global-abatement/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2014/2014-02-07-global-abatement/</guid><pubDate>Fri, 07 Feb 2014 00:00:00 GMT</pubDate><content:encoded>&lt;h3&gt;or, What the heck is global abatement?&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;tldr&lt;/strong&gt;: Global variables are &lt;a href=&quot;http://en.wikipedia.org/wiki/Code_smell&quot;&gt;code smells&lt;/a&gt;. Declaring variables inside an application-level function serves to namespace the variables and minimizes the use of global variables. &lt;!--more--&gt;&lt;/p&gt;
&lt;p&gt;Javascript has function-level scoping, which means that variables declared anywhere within a function are scoped to that function. Writing a javascript without an enclosing function leaves your declared variables vulnerable to name collisions, or reassignment by other javascripts.&lt;/p&gt;
&lt;p&gt;A &lt;strong&gt;global abatement&lt;/strong&gt; is a strategy used to reduce the vulnerability of your javascript variables by removing them from the global scope. Application namespacing is one such strategy:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;person &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;first_name&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Hello&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;last_name&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Kitty&apos;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;MYAPP&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token constant&quot;&gt;MYAPP&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;person &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;first_name&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Hello&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;last_name&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Kitty&apos;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Declaring an application-level function ensures that the correct &lt;code class=&quot;language-text&quot;&gt;person&lt;/code&gt; is called when needed. It improves readability by essentially flagging the scope of the variable and reducing ambiguity.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.amazon.com/gp/product/0596517742/ref=as_li_tf_tl?ie=UTF8&amp;#x26;camp=1789&amp;#x26;creative=9325&amp;#x26;creativeASIN=0596517742&amp;#x26;linkCode=as2&amp;#x26;tag=bridgeforpoke-20&quot;&gt;JavaScript: The Good Parts&lt;/a&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[fanout]]></title><description><![CDATA[Continuing my exploration of message queues… A common MQ modality is publish/subscribe. A simplistic queue model has producers publishing…]]></description><link>http://katieleonard.ca/blog/2014/2014-02-06-fanout/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2014/2014-02-06-fanout/</guid><pubDate>Thu, 06 Feb 2014 22:38:12 GMT</pubDate><content:encoded>&lt;p&gt;Continuing my exploration of message queues…&lt;/p&gt;
&lt;p&gt;A common MQ modality is publish/subscribe. A simplistic queue model has producers publishing messages directly to a queue and consumers taking messages off a queue. In the publish/subscribe model, the producer sends messages to an &lt;strong&gt;exchange&lt;/strong&gt;, who’s only job is to publish messages to queues. In this scenario, the exchange knows to which queue(s) the message should be published according to established rules. The relationship between an exchange and a queue is called a &lt;strong&gt;binding&lt;/strong&gt;.&lt;/p&gt;
&lt;!--more--&gt;
&lt;h3&gt;Types of exchanges&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;direct&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;topic&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;headers&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;fanout&lt;/strong&gt; - broadcasts every message it receives to all the queues it knows&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Create a fanout exchange:&lt;/h3&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ruby&quot;&gt;&lt;pre class=&quot;language-ruby&quot;&gt;&lt;code class=&quot;language-ruby&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# create and start the connection&lt;/span&gt;
connection &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Bunny&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
connection&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;start
&lt;span class=&quot;token comment&quot;&gt;# create and start the channel&lt;/span&gt;
channel &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; connection&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;create_channel
&lt;span class=&quot;token comment&quot;&gt;# create the exchange:&lt;/span&gt;
exchange &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; channel&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;fanout&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&apos;logs&apos;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# publish to your named exchange:&lt;/span&gt;
exchange&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;publish&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;msg&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# close the connection&lt;/span&gt;
connection&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;close&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;Create a fanout worker&lt;/h3&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ruby&quot;&gt;&lt;pre class=&quot;language-ruby&quot;&gt;&lt;code class=&quot;language-ruby&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# create and start the connection&lt;/span&gt;
connection &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Bunny&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
conn&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;start
&lt;span class=&quot;token comment&quot;&gt;# create and start the channel&lt;/span&gt;
channel  &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; connection&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;create_channel
&lt;span class=&quot;token comment&quot;&gt;# name the exchange to listen to&lt;/span&gt;
exchange &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; ch&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;fanout&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;logs&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# name the queue&lt;/span&gt;
q &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; ch&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;queue&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token symbol&quot;&gt;:exclusive&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# bind the queue to the exchange&lt;/span&gt;
q&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;bind&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;exchange&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# subscribe to the bound queue&lt;/span&gt;
q&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;subscribe&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token symbol&quot;&gt;:block&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt;delivery_info&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; properties&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; body&lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt;
  puts &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot; [x] &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token delimiter punctuation&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;token content&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;token delimiter punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;In action&lt;/h3&gt;
&lt;p&gt;Start three terminals:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;$ ruby -rubygems receive_logs.rb &gt; logs_from_rabbit.log&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;$ ruby -rubygems receive_logs.rb&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;$ ruby -rubygems emit_log.rb&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;In the last terminal, add a few more messages:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ ruby -rubygems emit_log.rb this is a longer message
$ ruby -rubygems emit_log.rb this message should be logged in a file AND appear in my terminal window&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The output in terminal 2:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ ruby -rubygems receive_logs.rb
 [*] Waiting for logs. To exit press CTRL+C
 [x] Hello World!
 [x] this is a longer message
 [x] this message should be logged in a file AND appear in my terminal&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The output from the log file:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ cat logs_from_rabbit.log
 [*] Waiting for logs. To exit press CTRL+C
 [x] Hello World!
 [x] this is a longer message
 [x] this message should be logged in a file AND appear in my terminal&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Resources&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://www.rabbitmq.com/tutorials/tutorial-three-ruby.html&quot;&gt;RabbitMQ.com&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[first in, first out]]></title><description><![CDATA[Why use message queues? Message queues offer the benefits of high reliability at the cost of performance. This is particularly useful for…]]></description><link>http://katieleonard.ca/blog/2014/2014-02-05-first-in-first-out/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2014/2014-02-05-first-in-first-out/</guid><pubDate>Wed, 05 Feb 2014 19:14:30 GMT</pubDate><content:encoded>&lt;h3&gt;Why use message queues?&lt;/h3&gt;
&lt;p&gt;Message queues offer the benefits of high reliability at the cost of performance. This is particularly useful for web tasks that may take longer than the typical HTTP request. Requests are persisted, acknowledged, and confirmed asynchronously. They are not dropped or timed out, no matter how long they take to process.&lt;/p&gt;
&lt;!--more--&gt;
&lt;h3&gt;Asynchronous request processing with RabbitMQ&lt;/h3&gt;
&lt;p&gt;A program that sends messages is a &lt;strong&gt;producer&lt;/strong&gt;. A producer drops a message onto a &lt;strong&gt;queue&lt;/strong&gt; (like a mailbox). A &lt;strong&gt;consumer&lt;/strong&gt; is a program that mostly waits to receive messages, and processes them when they arrive.&lt;/p&gt;
&lt;p&gt;RabbitMQ provides message acknowledgments. An ack(nowledgement) is sent back from the consumer to tell the queue that a particular message has been received and processed, and that the queue is free to delete it&lt;/p&gt;
&lt;h3&gt;Lets be fair&lt;/h3&gt;
&lt;p&gt;By default, RabbitMQ will dispatch messages equitably to all workers, and will not check first to see if the worker is already busy. You can ask the queue to only send messages to a worker if it is available to process a message.&lt;/p&gt;
&lt;p&gt;Use &lt;code class=&quot;language-text&quot;&gt;channel.prefetch(1)&lt;/code&gt; to prevent dispatching a new message to a worker until it has processed and acknowledged the previous one. Instead, RabbitMQ will dispatch it to the next worker that is not still busy. One possible ramification of prefetching is that the queue can become backed up if all workers are busy with long processes, so watch your queue length!&lt;/p&gt;
&lt;h3&gt;Useful Commands&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;list active queues: &lt;code class=&quot;language-text&quot;&gt;sudo rabbitmqctl list_queues&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;list queues along with unacknowledged messages: &lt;code class=&quot;language-text&quot;&gt;sudo rabbitmqctl list_queues name messages_ready messages_unacknowledged&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Resources&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://www.amazon.com/gp/product/B00HNG8ZFQ/ref=kinw_myk_ro_title&quot;&gt;Queue based system architecture&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://manning.com/videla/&quot;&gt;RabbitMQ in Action: Distributed messaging for everyone&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.rabbitmq.com/tutorials/tutorial-one-ruby.html&quot;&gt;RabbitMQ.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.rabbitmq.com/install-debian.html&quot;&gt;Installation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[Afraid of commitment]]></title><description><![CDATA[or, how to not fubar your git history As with all the git lessons I have learned, this one started with a huge mistake. I had merged a…]]></description><link>http://katieleonard.ca/blog/2014/2014-02-04-afraid-of-commitment/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2014/2014-02-04-afraid-of-commitment/</guid><pubDate>Tue, 04 Feb 2014 16:04:27 GMT</pubDate><content:encoded>&lt;h3&gt;or, how to not fubar your git history&lt;/h3&gt;
&lt;p&gt;As with all the git lessons I have learned, this one started with a huge mistake. I had merged a commit to master that was breaking pages I didn’t know existed. The sage developer sitting on my right shoulder told me that since I was unsure of how to fix the problem I should revert the offending commit forthwith. &lt;!--more--&gt;&lt;/p&gt;
&lt;p&gt;I had two choices of commit to revert:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;remove the offending commit from the branch history&lt;/li&gt;
&lt;li&gt;remove the merge commit, where the broken code had infiltrated master&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;While the former is like a surgical excision of a moment in history (eternal sunshine of a spotless git history?), the latter will preserve your branch history, and the context surrounding the changes made. I like a lot of context, so I chose to revert the merge commit.&lt;/p&gt;
&lt;p&gt;When you undo a merge, git doesn’t know how to reassign the branches. Was the left one master? The right? Does git know left from right? Who is on first? Take the guesswork out of the equation&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; checkout -b revert_branch_name
$ &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; revert -m &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;SHA of commit to be reverted&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Warning: If you don’t make the new branch first, you will mess up your merge history on master. Trust me. Just make the branch first. Now you can ensure that your test suite will pass with the commit reverted before you do something silly, like merge even more breakage into master. Crisis averted.&lt;/p&gt;
&lt;p&gt;Awesome.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Slack]]></title><description><![CDATA[Slack: Getting Past Burnout, Busywork and the Myth of Total Efficiency, by Tom DeMarco Trimming the slack from an organization in an effort…]]></description><link>http://katieleonard.ca/blog/2014/2014-02-03-slack/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2014/2014-02-03-slack/</guid><pubDate>Mon, 03 Feb 2014 16:06:13 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;http://www.amazon.com/gp/product/0932633617/ref=as_li_tf_tl?ie=UTF8&amp;#x26;camp=1789&amp;#x26;creative=9325&amp;#x26;creativeASIN=0932633617&amp;#x26;linkCode=as2&amp;#x26;tag=bridgeforpoke-20&quot;&gt;Slack&lt;/a&gt;: Getting Past Burnout, Busywork and the Myth of Total Efficiency, by Tom DeMarco&lt;/p&gt;
&lt;p&gt;Trimming the slack from an organization in an effort to reduce overhead will leave a company with an increased profit margin at the cost of becoming inflexible. “Slack is the natural enemy of efficiency, and efficiency is the natural enemy of slack.” Knowledge work cannot be optimized in the same manner as manufacturing because it is creative by nature, and creative work is requires immersion, experimentation, and… well.. slack.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[a number is a double is a float]]></title><description><![CDATA[JavaScript has a single number type — a 64-bit floating point number. Since there is no separate integer type, 1 and 1.0 are the same value…]]></description><link>http://katieleonard.ca/blog/2014/2014-02-02-a-number-is-a-double-is-a-float/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2014/2014-02-02-a-number-is-a-double-is-a-float/</guid><pubDate>Mon, 03 Feb 2014 03:56:17 GMT</pubDate><content:encoded>&lt;p&gt;JavaScript has a single number type — a 64-bit floating point number. Since there is no separate integer type, 1 and 1.0 are the same value.&lt;/p&gt;
&lt;!--more--&gt;
&lt;p&gt;One of the consequences is that the &lt;code class=&quot;language-text&quot;&gt;/&lt;/code&gt; operator may return a floating point number even if both operands are integers. Goodbye casting!&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.amazon.com/gp/product/0596517742/ref=as_li_tf_tl?ie=UTF8&amp;#x26;camp=1789&amp;#x26;creative=9325&amp;#x26;creativeASIN=0596517742&amp;#x26;linkCode=as2&amp;#x26;tag=bridgeforpoke-20&quot;&gt;JavaScript: The Good Parts&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Awesome.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[git add -p]]></title><description><![CDATA[I learned a new tool that has quickly become an essential part of my workflow.  lets you add small hunks of modified code to the index from…]]></description><link>http://katieleonard.ca/blog/2014/2014-02-01-git-add-p/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2014/2014-02-01-git-add-p/</guid><pubDate>Sun, 02 Feb 2014 04:51:09 GMT</pubDate><content:encoded>&lt;p&gt;I learned a new tool that has quickly become an essential part of my workflow. &lt;code class=&quot;language-text&quot;&gt;git add -p&lt;/code&gt;&lt;!--more--&gt; lets you add small hunks of modified code to the index from your working tree in order to prepare your next commit.&lt;/p&gt;
&lt;p&gt;The best refactors are small atomic changes, and while I may not always work incrementally, I still want my git history to reflect the ideal. I use &lt;code class=&quot;language-text&quot;&gt;git add -p&lt;/code&gt; before every commit to ensure that each code change is intentional.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt; -p
&lt;span class=&quot;token function&quot;&gt;diff&lt;/span&gt; --git a/send.rb b/send.rb
index 5e89eaf&lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;a0f25b6 &lt;span class=&quot;token number&quot;&gt;100644&lt;/span&gt;
--- a/send.rb
+++ b/send.rb
@@ -17,5 +17,5 @@ queue &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; channel.queue&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;hello&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
 channel.default_exchange.publish&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Hello world!&quot;&lt;/span&gt;, :routing_key &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; q.name&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
 puts &lt;span class=&quot;token string&quot;&gt;&quot; [x] Sent &apos;Hello World!&apos;&quot;&lt;/span&gt;

-&lt;span class=&quot;token comment&quot;&gt;# close the connection&lt;/span&gt;
-conn.close
&lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt; No newline at end of &lt;span class=&quot;token function&quot;&gt;file&lt;/span&gt;
+&lt;span class=&quot;token comment&quot;&gt;#close the connection&lt;/span&gt;
+connection.close
Stage this hunk &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;y,n,q,a,d,/,e,?&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;?&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Woah — that is a lot of information… lets go through by the numbers:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;the initial command&lt;/li&gt;
&lt;li&gt;tells me that it is showing the changes made in the send.rb file. ‘a’ is the version already in the commit history, and ‘b’ is the copy in the working directory.&lt;/li&gt;
&lt;li&gt;shows the commit SHA range for this branch&lt;/li&gt;
&lt;li&gt;tells me that lines marked with a ’-’ are from the committed version of send.rb&lt;/li&gt;
&lt;li&gt;tells me that lines marked with a ’+’ are from the working directory version of send.rb&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;@@ -17,5 +17,5 @@&lt;/code&gt; indicates that the hunk under scrutiny begins at line 17 of the committed version (‘-17’) and affects 5 lines. It corresponds to the working directory version starting at line 17 (‘+17’), also affecting 5 lines.&lt;/li&gt;
&lt;li&gt;the remaining lines contain the details of the changes in the hunk.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Know your options&lt;/h3&gt;
&lt;p&gt;Now that you have a hunk, what can you do with it?&lt;/p&gt;
&lt;p&gt; Type ’?’ to learn what you can do with your hunk&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;.
Stage this hunk &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;y,n,q,a,d,/,e,?&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; ?
y - stage this hunk
n - &lt;span class=&quot;token keyword&quot;&gt;do&lt;/span&gt; not stage this hunk
q - quit, &lt;span class=&quot;token keyword&quot;&gt;do&lt;/span&gt; not stage this hunk nor any of the remaining ones
a - stage this and all the remaining hunks &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; the &lt;span class=&quot;token function&quot;&gt;file&lt;/span&gt;
d - &lt;span class=&quot;token keyword&quot;&gt;do&lt;/span&gt; not stage this hunk nor any of the remaining hunks &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; the &lt;span class=&quot;token function&quot;&gt;file&lt;/span&gt;
g - &lt;span class=&quot;token keyword&quot;&gt;select&lt;/span&gt; a hunk to go to
/ - search &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; a hunk matching the given regex
j - leave this hunk undecided, see next undecided hunk
J - leave this hunk undecided, see next hunk
k - leave this hunk undecided, see previous undecided hunk
K - leave this hunk undecided, see previous hunk
s - &lt;span class=&quot;token function&quot;&gt;split&lt;/span&gt; the current hunk into smaller hunks
e - manually edit the current hunk
? - print &lt;span class=&quot;token builtin class-name&quot;&gt;help&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The first few options are obvious choices — &lt;code class=&quot;language-text&quot;&gt;y&lt;/code&gt; (“Yes, please!”), and &lt;code class=&quot;language-text&quot;&gt;n&lt;/code&gt; (“What was I thinking there?”), as well as &lt;code class=&quot;language-text&quot;&gt;q&lt;/code&gt; (“Hey, Jane! Get me off this crazy thing!”).&lt;/p&gt;
&lt;p&gt;I haven’t quite got a handle on the middle options, but I have skimmed down and used &lt;code class=&quot;language-text&quot;&gt;s&lt;/code&gt; to split the hunk into smaller pieces. Split will only divide a hunk if there is a logical place for separation, like a gap between changes. For real index-finesse and line-by-line control you have to… edit the hunk (gasp).&lt;/p&gt;
&lt;p&gt;Seasoned veterans may blanch at the thought of editing a hunk without a GUI, but I have discovered the secret to command-line-hunk-editing-prowess. The secret is:&lt;/p&gt;
&lt;h2&gt;Read the instructions&lt;/h2&gt;
&lt;p&gt;Revisiting the earlier example, I choose &lt;code class=&quot;language-text&quot;&gt;e&lt;/code&gt; to edit my hunk. I think the original comment on line 10 is better than the new one on line 13 (spacy == better). Selecting &lt;code class=&quot;language-text&quot;&gt;e&lt;/code&gt; opens your editor of choice with the now familiar hunk, along with…&lt;/p&gt;
&lt;p&gt;Lo, and behold! Instructions after the hunk!&lt;/p&gt;
&lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/bfc77017c2bc29278c03fe97bf968bd7/37523/addp-hunk-edit_diff-8.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 105.0632911392405%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAVCAIAAADJt1n/AAAACXBIWXMAAAsTAAALEwEAmpwYAAADX0lEQVQ4y6WS62rjRhTH9QyF7odNvLZk6z4jjUZX62JJlmTdbctxbAJLA6UUsruUNsS7XTaxnS6Edrt9jtKn6Uv0QYqjNOx+bAs/hsMZ/nPO/M8h7t5t7n7d//zxlw+/fXh/9/56v73eb3f73bu3bzebqzdvXl9eXu522/1+t9/vdrvtbrfdbm9ub/c3N9cEzVCxNaxdLzUMh+eVbg/3KGFAklSn1zsaDHoc1yfJ48Gg2+0+pWmSpimeHxw9/fLJky8IA8MrM341jC6s8MIMXzjRxk5vV+fpdJKn4/Ovzlan8+fPV6ens/W6WS6nI89KksCyMMaQEAFbYeOHevlNlF2k9Xf14tu4+Hq9WqwX+ays5mUYukkSOo4ZBI5t6xCwtmMEgeO6FsEDJtXMoY5Zvi8pIsaSIguqAm0EflrPXzUlyw0EgYGQB4BlGIphyMGg20IAiR8CMROkiSjFAjQY1uMEjeULnv7z6uUfr7+HQFA1bOiarqsQcgxDclyf4/osSx3aVjEoYjePR2U8sl3NDXQn0HxX/3h+dlFnPOCQLCIEAOBY9qB5hFAQ1C02bfhJBca5kBRiMQW6z88U9q/bH3/fHCprGjYMTZJEhiFputcqGYYkFAVYluJ4SNM5rLIS6ksyzbMMy9OaIhoYMlxfEBhJEiDkZFmQJJ7nBw+VERJ9346ioK6LusoRAr5v13U6mYTzpqymeeA7osi6njUcakHg+CNbloV/2lbAcKiGoTsee0kSeCOrDe5fHPm+nabjcTSCkCPJI4rqUFTnwe3+M0JVoedZlqXeo9m27jqmaammobiuibFkGNj37eFQ0zWkqQhjqGDouqZhYgLJouPoRZEsTqZZFmdZdHZ2UlZpGLpVmc6meRT5ZZk2izrPk8XhjCZpeHIyS9MxoapSEDjNol6tFk1TLxbTw29n5XRWLJezaZ3leTKfV3kR11VWFpP5vFqtmqapdE0+iCFkZflgpiQJCIkQsAoCGEOkAEniZfk+CbkWhICuI4wlmu4R7a7QdI9hyMMYmV47zJY2+Rn0w+3B7U835t/y/8Ttlv83CJI8bqGozwKK6vT7zz6FojokefwYU1SHqKqiKvOqzIsiK4qsrIo8n1RlnueTIPAe8X03jsOqysdjPwi8LEuCwPsbBacUO2Mb/I4AAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;addp hunk edit diff 8&quot; title=&quot;addp hunk edit diff 8&quot; src=&quot;/static/bfc77017c2bc29278c03fe97bf968bd7/f058b/addp-hunk-edit_diff-8.png&quot; srcset=&quot;/static/bfc77017c2bc29278c03fe97bf968bd7/c26ae/addp-hunk-edit_diff-8.png 158w,
/static/bfc77017c2bc29278c03fe97bf968bd7/6bdcf/addp-hunk-edit_diff-8.png 315w,
/static/bfc77017c2bc29278c03fe97bf968bd7/f058b/addp-hunk-edit_diff-8.png 630w,
/static/bfc77017c2bc29278c03fe97bf968bd7/37523/addp-hunk-edit_diff-8.png 720w&quot; sizes=&quot;(max-width: 630px) 100vw, 630px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot; loading=&quot;lazy&quot;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
&lt;p&gt;Simple enough:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;-# close the connection&lt;/code&gt; becomes &lt;code class=&quot;language-text&quot;&gt;# close the connection&lt;/code&gt; — mind the space!&lt;/li&gt;
&lt;li&gt;remove &lt;code class=&quot;language-text&quot;&gt;+#close the connection&lt;/code&gt; entirely&lt;/li&gt;
&lt;li&gt;save and close.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Success? If you have done everything right, the hunk will be staged and git will move on to the next hunk in your working directory. If you have made an error you will see the following message:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;Your edited hunk does not apply.
Edit again (saying &quot;no&quot; discards!) [y/n]?&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Aw nuts. &lt;code class=&quot;language-text&quot;&gt;y&lt;/code&gt; will let you amend your transgressions (did you remember to save? did you forget to leave a space in place of the ’-’?), and &lt;code class=&quot;language-text&quot;&gt;n&lt;/code&gt; will abandon your changes and take you back to the drawing board, where you are free to transgress anew.&lt;/p&gt;
&lt;p&gt;Awesome.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[git retrieve: a drama]]></title><description><![CDATA[Have you ever deleted a file on impulse, only to wake up with remorse later? It doesn’t matter if later is the next morning or the next week…]]></description><link>http://katieleonard.ca/blog/2014/2014-01-23-git-retrieve/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2014/2014-01-23-git-retrieve/</guid><pubDate>Fri, 24 Jan 2014 04:47:46 GMT</pubDate><content:encoded>&lt;p&gt;Have you ever deleted a file on impulse, only to wake up with remorse later? It doesn’t matter if later is the next morning or the next week, thanks to git you have the power to reanimate gone-but-not-forgotten files. Nothing is &lt;del&gt;ever&lt;/del&gt; EVER lost with git. So how do you retrieve a file that has been deleted in a previous commit?&lt;/p&gt;
&lt;!--more--&gt;
&lt;p&gt;&lt;a href=&quot;http://stackoverflow.com/a/953573&quot;&gt;stackoverflow&lt;/a&gt; has a few suggestions, and I like this one the best:&lt;/p&gt;
&lt;h3&gt;Git Drama in Three Acts&lt;/h3&gt;
&lt;p&gt;Act 1 Scene 1: foo.bar Folly&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ &lt;span class=&quot;token builtin class-name&quot;&gt;cd&lt;/span&gt; ~/very_important_project/
$ &lt;span class=&quot;token function&quot;&gt;touch&lt;/span&gt; readme.md index.html foo.bar
$ &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; commit -am &lt;span class=&quot;token string&quot;&gt;&quot;These changes are AWESOME.&quot;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;master &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;root-commit&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; 9155e0b&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; These changes are AWESOME.
 &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; files changed, &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; insertions&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;+&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;, &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; deletions&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;-&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
 create mode &lt;span class=&quot;token number&quot;&gt;100644&lt;/span&gt; foo.bar
 create mode &lt;span class=&quot;token number&quot;&gt;100644&lt;/span&gt; index.html
 create mode &lt;span class=&quot;token number&quot;&gt;100644&lt;/span&gt; readme.md&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;but wait! &lt;code class=&quot;language-text&quot;&gt;foo.bar&lt;/code&gt;?! that is just crazy talk?&lt;/p&gt;
&lt;p&gt;Act 1 Scene 2: Regret&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;rm&lt;/span&gt; foo.bar
&lt;span class=&quot;token function&quot;&gt;rm&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;foo.bar&apos;&lt;/span&gt;
$ &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt; -u
$ &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; commit -m &lt;span class=&quot;token string&quot;&gt;&quot;I have made a huge mistake.&quot;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;master b045a52&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; I have made a huge mistake.
 &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; files changed, &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; insertions&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;+&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;, &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; deletions&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;-&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
 delete mode &lt;span class=&quot;token number&quot;&gt;100644&lt;/span&gt; foo.bar&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Everything seems back to normal!
Act 2 Scene 1: I have made good life-choices&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ &lt;span class=&quot;token builtin class-name&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;#I rock and I am smug about it!&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; bar.rb
$ &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; commit -am &lt;span class=&quot;token string&quot;&gt;&quot;This work is the BOMB.&quot;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;master 3535f28&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; This work is the BOMB.
 &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; files changed, &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; insertions&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;+&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;, &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; deletions&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;-&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
 create mode &lt;span class=&quot;token number&quot;&gt;100644&lt;/span&gt; bar.rb
$ &lt;span class=&quot;token function&quot;&gt;cat&lt;/span&gt; foo.bar
cat: foo.bar: No such &lt;span class=&quot;token function&quot;&gt;file&lt;/span&gt; or directory you heartless creature&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;but wait! there is no bar without a foo! where is my foo.bar? How can I find it? I have to find the commit where it was deleted, but how? What if I list out the commits that include a deleted file?&lt;/p&gt;
&lt;p&gt;Act 2 Scene 2: Regret&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; log --diff-filter&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;D --summary
commit b045a528b4a0824f63562cad867b264983b32c7c
Author: keighty &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;keighty.leonard@gmail.com&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
Date:   Wed Jan &lt;span class=&quot;token number&quot;&gt;22&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;20&lt;/span&gt;:46:16 &lt;span class=&quot;token number&quot;&gt;2014&lt;/span&gt; -0800

    I have made a huge mistake.

 delete mode &lt;span class=&quot;token number&quot;&gt;100644&lt;/span&gt; foo.bar&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;There you are! in commit b045a528. The summary option shows the details, so you can see what files were deleted, when, and by whom. In some cases, there may be more than one change in a commit, so using &lt;code class=&quot;language-text&quot;&gt;commitSHA~1 &amp;lt;filename&gt;&lt;/code&gt; will pluck the one precious deleted file from the commit and restore it to your working tree.&lt;/p&gt;
&lt;p&gt;Act 3: foo.bar’s Return&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; checkout b045a528~1 foo.bar
$ &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; status
&lt;span class=&quot;token comment&quot;&gt;# On branch master&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# Changes to be committed:&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;#   (use &quot;git reset HEAD &amp;lt;file&gt;...&quot; to unstage)&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;#&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# new file:   foo.bar&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;#&lt;/span&gt;
$ &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; commit -am &lt;span class=&quot;token string&quot;&gt;&quot;Together at last, together forever.&quot;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;master 8492eac&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; Together at last, together forever.
 &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; files changed, &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; insertions&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;+&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;, &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; deletions&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;-&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
 create mode &lt;span class=&quot;token number&quot;&gt;100644&lt;/span&gt; foo.bar&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;EXEUNT.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[mongod maintenance]]></title><description><![CDATA[My laptop’s battery died, and I let it. Not a big deal, it is an old laptop and is used to being abused. Every time it does a hard shut down…]]></description><link>http://katieleonard.ca/blog/2014/2014-01-22-maintaining-mongod/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2014/2014-01-22-maintaining-mongod/</guid><pubDate>Wed, 22 Jan 2014 15:23:10 GMT</pubDate><content:encoded>&lt;p&gt;My laptop’s battery died, and I let it. Not a big deal, it is an old laptop and is used to being abused. Every time it does a hard shut down like that I wonder if it will recover. The laptop recovered just fine, but mongo did not. When my computer coughed back to life, I politely requested a meteor server, to which meteor replied that it could not start my server because it could not find a running mongodb. My first instinct, naturally, was to start it up again&lt;!--more--&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ mongo start
MongoDB shell version: &lt;span class=&quot;token number&quot;&gt;2.4&lt;/span&gt;.6
connecting to: start
Mon Jan &lt;span class=&quot;token number&quot;&gt;20&lt;/span&gt; 07:42:47.289 Error: couldn&apos;t connect to server &lt;span class=&quot;token number&quot;&gt;127.0&lt;/span&gt;.0.1:27017 at src/mongo/shell/mongo.js:145
exception: connect failed&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Followed by a trip to the logs:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ &lt;span class=&quot;token function&quot;&gt;tail&lt;/span&gt; /var/log/mongodb/mongodb.log
*************
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;initandlisten&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; exception &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; initAndListen: &lt;span class=&quot;token number&quot;&gt;10309&lt;/span&gt; Unable to create/open lock file: /var/lib/mongodb/mongod.lock errno:13 Permission denied Is a mongod instance already running?, terminating
dbexit:
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;initandlisten&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; shutdown: going to close listening sockets&lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;.
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;initandlisten&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; shutdown: going to flush diaglog&lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;.
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;initandlisten&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; shutdown: going to close sockets&lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;.
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;initandlisten&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; shutdown: waiting &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; fs preallocator&lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;.
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;initandlisten&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; shutdown: closing all files&lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;.
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;initandlisten&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; closeAllFiles&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; finished
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;initandlisten&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; shutdown: removing fs lock&lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;.
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;initandlisten&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; couldn&apos;t remove fs lock errno:9 Bad &lt;span class=&quot;token function&quot;&gt;file&lt;/span&gt; descriptor
dbexit: really exiting now&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;A lock file, you say? Well! I know what to do with those!&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ &lt;span class=&quot;token function&quot;&gt;rm&lt;/span&gt; /var/lib/mongodb/mongod.lock
rm: remove write-protected regular &lt;span class=&quot;token function&quot;&gt;file&lt;/span&gt; `/var/lib/mongodb/mongod.lock&apos;? n&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;No, I am not sure — thanks for asking! After a deep breath and a reminder that I should not be so hasty (rtfm, katie), I found this note on &lt;a href=&quot;http://docs.mongodb.org/manual/reference/configuration-options/#repair&quot;&gt;mongodb.org&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Note: Because mongod rewrites all of the database files during the repair routine, if you do not run repair under the same user account as mongod usually runs, you will need to run chown on your database files to correct the permissions before starting mongod again.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;A file rewrite will include a lock file, will it not?&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ &lt;span class=&quot;token function&quot;&gt;sudo&lt;/span&gt; -u mongodb mongod --repair --dbpath /var/lib/mongodb/
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;sudo&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; password &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; keighty:
&lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;.
&lt;span class=&quot;token function&quot;&gt;sudo&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;service&lt;/span&gt; mongodb start&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Awesome.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[embrace HRT for collabrative nirvana]]></title><description><![CDATA[Team Geek: A Software Developer’s Guide to Working Well with Others by Brian W. Fitzpatrick and Ben Collins-Sussman. With decades of…]]></description><link>http://katieleonard.ca/blog/2014/2014-01-20-embrace-hrt-for-collabrative-nirvana/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2014/2014-01-20-embrace-hrt-for-collabrative-nirvana/</guid><pubDate>Mon, 20 Jan 2014 15:07:15 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;http://www.amazon.com/gp/product/1449302440/ref=as_li_tf_tl?ie=UTF8&amp;#x26;camp=1789&amp;#x26;creative=9325&amp;#x26;creativeASIN=1449302440&amp;#x26;linkCode=as2&amp;#x26;tag=keighty-20&quot;&gt;Team Geek: A Software Developer’s Guide to Working Well with Others&lt;/a&gt; by Brian W. Fitzpatrick and Ben Collins-Sussman.&lt;/p&gt;
&lt;p&gt;With decades of collective experience, these two authors distill the essential philosophy required to be part of a healthy development team: HRT — humility, respect, and trust. These values are covered in the first chapter and the remainder of the book describes how to best use them as an engineer and as a manager. Some techniques particularly resonated with my world view.&lt;!--more--&gt;&lt;/p&gt;
&lt;h3&gt;Fail early. Fail fast. Fail often&lt;/h3&gt;
&lt;p&gt;It is easy to pay lip-service to this philosophy, but it is impossible to adopt without a culture of HRT. From my own limited experience I can add — Communicate early. Communicate fast. Communicate often. — as another mantra of healthy team dynamics. Failure is always an option, but without HRT and open lines of communication it can take much more time to discover.&lt;/p&gt;
&lt;h3&gt;Make time vs manager time&lt;/h3&gt;
&lt;p&gt;Fitzpatrick and Collins-Sussman drew on a lot of great resources, and there is as much gold in the footnotes as there is in the text. They referenced Paul Graham’s essay, &lt;a href=&quot;http://www.paulgraham.com/makersschedule.html&quot;&gt;Maker’s Schedule&lt;/a&gt;, in which he contrasts the different working styles of managers and makers (writers or programmers). The manager’s schedule can be divided into hour-long chunks that may be apportioned to meetings, appointments, or tasks.: the essence of David Allen’s &lt;a href=&quot;http://www.davidco.com/about-gtd&quot;&gt;GTD&lt;/a&gt; (Getting Things Done). Makers, on the other hand, cannot be effective in one hour intervals. Graham writes that a single meeting in the afternoon can affect the productivity for a whole day. First it breaks up the afternoon into two pieces that are not long enough to really get into the zone, then it psychologically leaks into the morning where you are “less likely to start something ambitious”. I can definitely identify with this propensity. The cost of task switching around meetings often results in a lost day.&lt;/p&gt;
&lt;h3&gt;Core values&lt;/h3&gt;
&lt;p&gt;HRT is the heart of high-functioning teams of any ilk. When I was interviewing for my first job in software development (all those weeks ago) the most difficult question an interviewer could pose to me was “where do you see yourself in 5 years”? It was difficult because I had just spent the last five years dreaming about writing code for a living. I couldn’t even verbalize what I was looking for in a company, only that I would know it when I met it. Now I can identify the traits I was looking for: teams that value writing code and shipping product, consensus based team decision making, asynchronous communication (I am not room-meat), and of course, they’ve got to have HeaRT.&lt;/p&gt;
&lt;p&gt;Awesome.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[open-source setup:]]></title><description><![CDATA[the Ego. In the interests of giving back to the software community, I have been looking for an active open-source project to contribute to…]]></description><link>http://katieleonard.ca/blog/2014/2014-01-18-opensource-setup-git-checkout-the-ego/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2014/2014-01-18-opensource-setup-git-checkout-the-ego/</guid><pubDate>Sat, 18 Jan 2014 19:18:29 GMT</pubDate><content:encoded>&lt;h2&gt;&lt;code class=&quot;language-text&quot;&gt;git checkout&lt;/code&gt; the Ego.&lt;/h2&gt;
&lt;p&gt;In the interests of giving back to the software community, I have been looking for an active open-source project to contribute to. I am working to gain mastery of ruby on rails, so naturally I gravitate towards projects of that ilk. Unfortunately, I have gained just enough knowledge to be a little smug, so when I found a project I wanted to work on I scrolled immediately to the README and started scanning.&lt;!--more--&gt; The first block of text was headed by:&lt;/p&gt;
&lt;h3&gt;Start here if this is your first ruby on rails project…&lt;/h3&gt;
&lt;p&gt;…with a link to a blog post. I kept scanning for information that would be relevant to ME. This was not my first ruby on rails project. I have my elaborate dev environment set up just the way I like it, thank you very much, and I can reproduce your project with a flick of my config file, I am sure (chuckles condescendingly). This is a snippet of the proceeding workflow:&lt;/p&gt;
&lt;p&gt;Workflow of the egotistical programmer.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; clone repo
$ &lt;span class=&quot;token builtin class-name&quot;&gt;cd&lt;/span&gt; repo/
$ bundle &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt;
Errors: need to update your rubygems
$ gem update --system
$ bundle &lt;span class=&quot;token builtin class-name&quot;&gt;exec&lt;/span&gt; rake db:setup
Errors: need postgres installed &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;no inkling &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; the README&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
$ brew &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; postgres
&lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;. follow half of the required instructions
Errors
Frustration because you don&apos;t know how to follow instructions
$ brew info postgres
&lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;.
&lt;span class=&quot;token string&quot;&gt;&quot;ooooohhhhhhhh... I missed a step&quot;&lt;/span&gt;
$ follow instructions this &lt;span class=&quot;token function&quot;&gt;time&lt;/span&gt;
$ bundle &lt;span class=&quot;token builtin class-name&quot;&gt;exec&lt;/span&gt; rake db:setup
Errors: need redis installed
$ brew &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; redis
$ follow instructions because I have learned my lesson
$ bundle &lt;span class=&quot;token builtin class-name&quot;&gt;exec&lt;/span&gt; rake db:setup
Errors: redis config &lt;span class=&quot;token function&quot;&gt;file&lt;/span&gt; missing information
Frustration because redis config &lt;span class=&quot;token function&quot;&gt;file&lt;/span&gt; was removed &lt;span class=&quot;token number&quot;&gt;100&lt;/span&gt; commits ago
&lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;.
Determine that first pull request
will be an amendment to setup documentation
Rebuild config &lt;span class=&quot;token function&quot;&gt;file&lt;/span&gt; and &lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;host&lt;/span&gt; name
$ bundle &lt;span class=&quot;token builtin class-name&quot;&gt;exec&lt;/span&gt; rake db:setup
Errors: required seeds &lt;span class=&quot;token function&quot;&gt;file&lt;/span&gt; was removed &lt;span class=&quot;token number&quot;&gt;100&lt;/span&gt; commits ago
$ bundle &lt;span class=&quot;token builtin class-name&quot;&gt;exec&lt;/span&gt; rake db:migrate
$ SUCCESS&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;
$ bundle &lt;span class=&quot;token builtin class-name&quot;&gt;exec&lt;/span&gt; rake spec
Errors: run db:test:prepare
$ bundle &lt;span class=&quot;token builtin class-name&quot;&gt;exec&lt;/span&gt; rake db:test:prepare
Errors
Frustration
$ &lt;span class=&quot;token assign-left variable&quot;&gt;RAILS_ENV&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;test bundle &lt;span class=&quot;token builtin class-name&quot;&gt;exec&lt;/span&gt; rake db:migrate
$ SUCCESS&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;
$ bundle &lt;span class=&quot;token builtin class-name&quot;&gt;exec&lt;/span&gt; rake spec
Errors&lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;. sigh&lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;more&lt;/span&gt; errors
$ limp away &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; lunch, live to contribute another day&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Getting a new project setup and functional is not an easy chore, and I was quite chastened when I swallowed my pride and checked out the blog post for first timers, which boiled down to:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Install &lt;a href=&quot;https://www.virtualbox.org/wiki/Downloads&quot;&gt;VirtualBox&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Install &lt;a href=&quot;http://www.vagrantup.com/&quot;&gt;Vagrant&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;git clone repo&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;cd repo&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;vagrant up&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;vagrant ssh&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;cd /vagrant&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;bundle install&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;bundle exec rake db:migrate&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;bundle exec rails s&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I could have been contributing hours ago, when I still had momentum! Perhaps my first pull request should still be to modify the README. I would rephrase the heading to read “For all developers: get started right here”, and then remove every other instruction that followed.&lt;/p&gt;
&lt;p&gt;Perhaps I should go get started…&lt;/p&gt;
&lt;p&gt;Awesome.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Meteor user]]></title><description><![CDATA[“Getting Started with Meteor.js JavaScript Framework” by Isaac Strack is a great introduction to a powerful tool. User accounts in three…]]></description><link>http://katieleonard.ca/blog/2014/2014-01-14-meteor-user/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2014/2014-01-14-meteor-user/</guid><pubDate>Wed, 15 Jan 2014 03:38:16 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;http://www.packtpub.com/getting-started-with-meteor-javascript-framework/book&quot;&gt;“Getting Started with Meteor.js JavaScript Framework”&lt;/a&gt; by Isaac Strack is a great introduction to a powerful tool.&lt;/p&gt;
&lt;!--more--&gt;
&lt;h3&gt;User accounts in three easy steps&lt;/h3&gt;
&lt;p&gt;Meteor rolls its own user accounts system, and getting it running on your application is a three step process:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;command line: Add the relevant packages&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ meteor &lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt; accounts-base
accounts-base: A user account system
$ meteor &lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt; accounts-password
accounts-password: Password support &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; accounts
$ meteor &lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt; email
email: Send email messages
$ meteor &lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt; accounts-ui
accounts-ui: Simple templates to &lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt; login widgets to an app&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;html: Add a div to hold the login button&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;html&quot;&gt;&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token special-attr&quot;&gt;&lt;span class=&quot;token attr-name&quot;&gt;style&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token value css language-css&quot;&gt;&lt;span class=&quot;token property&quot;&gt;float&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;right&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;margin-right&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;20px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
{{loginButtons align=&quot;right&quot;}}
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;client javascript: Add an Accounts config&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;Accounts&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ui&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;token literal-property property&quot;&gt;passwordSignupFields&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;USERNAME_AND_OPTIONAL_EMAIL&apos;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;The catch&lt;/h2&gt;
&lt;p&gt;While the server side and client side code looks similar they are definitely not interchangeable. Server code run on the client side will likely fail silently, but client code run on the server will crash the app. One place where I got tripped up was accessing the userId:&lt;/p&gt;
&lt;h3&gt;Server side &lt;code class=&quot;language-text&quot;&gt;this.userId&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;In Meteor server side javascript the context is clear: &lt;code class=&quot;language-text&quot;&gt;this&lt;/code&gt; is called in the context of a Meteor object, and you can therefore make inquiries about its properties. {“Use this.userId inside the server publish function”} to access the id of the current user (or null if no user is logged in — from the &lt;a href=&quot;http://docs.meteor.com/#publish_userId&quot;&gt;docs&lt;/a&gt;).&lt;/p&gt;
&lt;h3&gt;Client side: &lt;code class=&quot;language-text&quot;&gt;Meteor.userId()&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;In the Meteor client side, &lt;code class=&quot;language-text&quot;&gt;this&lt;/code&gt; has a different context: the &lt;code class=&quot;language-text&quot;&gt;window&lt;/code&gt; object. The window object has a userId property that can be set at Document.ready(), but in the case that a user logs out and another user logs in to that same window without a page refresh, &lt;code class=&quot;language-text&quot;&gt;window.userId&lt;/code&gt; will retain the id of the first user. {“Use Meteor.userId() anywhere BUT in the server publish function”} to get the current user id (or null if no user is logged in — from the &lt;a href=&quot;http://docs.meteor.com/#accounts_api&quot;&gt;docs&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;Thanks to this &lt;a href=&quot;http://stackoverflow.com/a/20781135&quot;&gt;stackoverflow&lt;/a&gt; response, the Meteor &lt;a href=&quot;http://docs.meteor.com/&quot;&gt;docs&lt;/a&gt;, and packtpub’s awesome &lt;a href=&quot;http://www.packtpub.com/getting-started-with-meteor-javascript-framework/book&quot;&gt;support page&lt;/a&gt; for helping me get reacquainted with javascript contexts.&lt;/p&gt;
&lt;p&gt;Awesome&lt;/p&gt;</content:encoded></item><item><title><![CDATA[get clean]]></title><description><![CDATA[I experiment a lot before I choose an implementation I like. I am sure I am not alone in making a few (or many) false starts, and yet…]]></description><link>http://katieleonard.ca/blog/2014/2014-01-13-get-clean/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2014/2014-01-13-get-clean/</guid><pubDate>Tue, 14 Jan 2014 05:29:03 GMT</pubDate><content:encoded>&lt;p&gt;I experiment a lot before I choose an implementation I like. I am sure I am not alone in making a few (or many) false starts, and yet feeling sick at the thought of deleting any code. What if one of those paths I started down was the right one? This loss aversion often leads to working trees of non-working code, and &lt;code class=&quot;language-text&quot;&gt;git stash&lt;/code&gt;-es that I will never revisit. If I stop myself from going too far down yet another road without an end in sight, attempts to clean up my working directory often stall miserably at the end of a &lt;code class=&quot;language-text&quot;&gt;git checkout .&lt;/code&gt;:&lt;!--more--&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;On branch intelligent_branch_name
&lt;span class=&quot;token comment&quot;&gt;# Untracked files:&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;#   (use &quot;git add &amp;lt;file&gt;...&quot; to include in what will be committed)&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;#&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# ../test/yay_I_wrote_tests.rb&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# ../helpers/yay_I_wrote_a_helper.rb&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# ../helpers/how_many_helpers_did_I_write.rb&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# ../views/i_dont_remember_creating_this_file.rb&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# ../models/oh_thats_where_that_went.rb&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Once upon a time, I would click my way through &lt;code class=&quot;language-text&quot;&gt;rm&lt;/code&gt; after &lt;code class=&quot;language-text&quot;&gt;rm&lt;/code&gt;. A small improvement in &lt;code class=&quot;language-text&quot;&gt;rm&lt;/code&gt; efficiency came when I discovered I could &lt;code class=&quot;language-text&quot;&gt;rm&lt;/code&gt; more than one file at a time (don’t judge me, I am new at this). Still, the biggest break-through came when a coworker, perhaps observing my struggles, pointed me to &lt;a href=&quot;http://ndpsoftware.com/git-cheatsheet.html&quot;&gt;git-cheatsheet&lt;/a&gt; — a interactive visual tool to display the relevant commands for each stage of my git workflow.&lt;/p&gt;
&lt;h3&gt;Enter &lt;code class=&quot;language-text&quot;&gt;git clean&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;Git clean is a force to be reckoned with, and not just because it doesn’t do anything unless you force it.&lt;/p&gt;
&lt;p&gt;Use the -n flag to describe the action the cleaner would take&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; clean -n
Would remove &lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;/helpers/yay_I_wrote_a_helper.rb
Would remove &lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;/helpers/how_many_helpers_did_I_write.rb
Would remove &lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;/views/i_dont_remember_creating_this_file.rb
Would remove &lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;/models/oh_thats_where_that_went.rb
$&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Use the -f flag to force the cleanup&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; clean -f
removed &lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;/helpers/yay_I_wrote_a_helper.rb
removed &lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;/helpers/how_many_helpers_did_I_write.rb
removed &lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;/views/i_dont_remember_creating_this_file.rb
removed &lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;/models/oh_thats_where_that_went.rb
$&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now I can be as crufty as I want to be in my working tree, because &lt;code class=&quot;language-text&quot;&gt;git&lt;/code&gt; will be there to clean up the mess.&lt;/p&gt;
&lt;p&gt;Awesome.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Factoring In Nests]]></title><description><![CDATA[I am building an application that uses several nested attributes: Users have many Goals (Goals belongto Users), and Goals have many Hours…]]></description><link>http://katieleonard.ca/blog/2013/2013-10-29-factoring-in-nests/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2013/2013-10-29-factoring-in-nests/</guid><pubDate>Wed, 30 Oct 2013 05:29:03 GMT</pubDate><content:encoded>&lt;p&gt;I am building an application that uses several nested attributes: Users have many Goals (Goals belong&lt;em&gt;to Users), and Goals have many Hours (Hours belong&lt;/em&gt;to Goals).&lt;/p&gt;
&lt;p&gt;Using &lt;a href=&quot;https://github.com/thoughtbot/factory_girl&quot;&gt;FactoryGirl&lt;/a&gt; to create a User is straightforward:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ruby&quot;&gt;&lt;pre class=&quot;language-ruby&quot;&gt;&lt;code class=&quot;language-ruby&quot;&gt;FactoryGirl&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;define &lt;span class=&quot;token keyword&quot;&gt;do&lt;/span&gt;
  factory &lt;span class=&quot;token symbol&quot;&gt;:user&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;do&lt;/span&gt;
    sequence &lt;span class=&quot;token symbol&quot;&gt;:name&lt;/span&gt;  &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt;n&lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;person&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token delimiter punctuation&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;token content&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;token delimiter punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    sequence &lt;span class=&quot;token symbol&quot;&gt;:email&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt;n&lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;person&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token delimiter punctuation&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;token content&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;token delimiter punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;@example.com&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;end&lt;/span&gt;

describe User &lt;span class=&quot;token keyword&quot;&gt;do&lt;/span&gt;
  before  &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;@user&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; FactoryGirl&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;create&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token symbol&quot;&gt;:user&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  subject &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;@user&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  it &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; should respond_to&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token symbol&quot;&gt;:name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;How do I create Goals that are linked to the User?&lt;/p&gt;
&lt;!--more--&gt;
&lt;h3&gt;How to create Factories for nested attributes&lt;/h3&gt;
&lt;h5&gt;1. Make a new Factory for producing Goals:&lt;/h5&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ruby&quot;&gt;&lt;pre class=&quot;language-ruby&quot;&gt;&lt;code class=&quot;language-ruby&quot;&gt;FactoryGirl&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;define &lt;span class=&quot;token keyword&quot;&gt;do&lt;/span&gt;
  factory &lt;span class=&quot;token symbol&quot;&gt;:goal&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;do&lt;/span&gt;
    sequence &lt;span class=&quot;token symbol&quot;&gt;:description&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt;n&lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;my goal &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token delimiter punctuation&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;token content&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;token delimiter punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    sequence &lt;span class=&quot;token symbol&quot;&gt;:motivation&lt;/span&gt;  &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt;n&lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;my motivation &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token delimiter punctuation&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;token content&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;token delimiter punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h5&gt;2. Call the Goal Factory from the User Factory and store the Goals in an Array&lt;/h5&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ruby&quot;&gt;&lt;pre class=&quot;language-ruby&quot;&gt;&lt;code class=&quot;language-ruby&quot;&gt;FactoryGirl&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;define &lt;span class=&quot;token keyword&quot;&gt;do&lt;/span&gt;
  factory &lt;span class=&quot;token symbol&quot;&gt;:user&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;do&lt;/span&gt;
    sequence &lt;span class=&quot;token symbol&quot;&gt;:name&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt;n&lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;person&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token delimiter punctuation&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;token content&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;token delimiter punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    sequence &lt;span class=&quot;token symbol&quot;&gt;:email&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt;n&lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;person&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token delimiter punctuation&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;token content&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;token delimiter punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;@example.com&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    goals &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Array&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; FactoryGirl&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;build&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token symbol&quot;&gt;:goal&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Your objects will look like this:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; p @user
&lt;span class=&quot;token comment&quot;&gt;#&amp;lt;User id: 1, name: &quot;person1&quot;, email: &quot;person1@example.com&quot;, ... &gt;&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; p @user.goals.first
&lt;span class=&quot;token comment&quot;&gt;#&amp;lt;ActiveRecord::Associations::CollectionProxy [#&amp;lt;Goal id: 1, user_id: 1, description: &quot;my goal 1&quot;, motivation: &quot;my motivation 1&quot;, ...]&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Create Hours for Goals in the same manner: create a Factory for making Hours, call the Hours Factory from the Goals Factory.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;FactoryGirl.define do
  factory :hour do
    duration { 100 * rand(36) }
    ...
  end
end

FactoryGirl.define do
  factory :goal do
    sequence :description { |n| &quot;my goal #{n}&quot; }
    sequence :motivation  { |n| &quot;my motivation #{n}&quot; }

    hours { Array.new(3) { FactoryGirl.build(:hour) } }
  end
end&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Checking your objects:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; p @user
&lt;span class=&quot;token comment&quot;&gt;#&amp;lt;User id: 1, name: &quot;person1&quot;, email: &quot;person1@example.com&quot;, ... &gt;&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; p @user.goals.first
&lt;span class=&quot;token comment&quot;&gt;#&amp;lt;ActiveRecord::Associations::CollectionProxy [#&amp;lt;Goal id: 1, user_id: 1, description: &quot;my goal 1&quot;, motivation: &quot;my motivation 1&quot;, ...]&gt;&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; p @user.goals.first.hours.first
&lt;span class=&quot;token comment&quot;&gt;#&amp;lt;ActiveRecord::Associations::CollectionProxy [#&amp;lt;Hour id: 1, goal_id: 1, duration: 3200 , ...]&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Awesome.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Meatier Apps With Meteor]]></title><description><![CDATA[Meteor is a framework that allows you to write web applications using only javascript. All the work is done on the client-side. Meteor…]]></description><link>http://katieleonard.ca/blog/2013/2013-09-20-meatier-apps-with-meteor/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2013/2013-09-20-meatier-apps-with-meteor/</guid><pubDate>Mon, 21 Oct 2013 05:29:03 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;http://www.meteor.com/&quot;&gt;Meteor&lt;/a&gt; is a framework that allows you to write web applications using only javascript. All the work is done on the client-side. Meteor embraces new principles of web design: data on the wire, one language is enough, and simplicity makes for productivity.&lt;/p&gt;
&lt;p&gt;Simplicity is something I value as well, and while setting up meteor on my linux machine was not a three-step process as outlined in their examples, it only took a little tinkering to figure out the problem. &lt;!--more--&gt;First, a look at the three meteor setup steps:&lt;/p&gt;
&lt;h4&gt;Install&lt;/h4&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ &lt;span class=&quot;token function&quot;&gt;curl&lt;/span&gt; https://install.meteor.com &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; /bin/sh&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h4&gt;Create a sample application&lt;/h4&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ meteor create testapp&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h4&gt;Run the sample application&lt;/h4&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ &lt;span class=&quot;token builtin class-name&quot;&gt;cd&lt;/span&gt; testapp
$ meteor&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This is where the meteor server is supposed to start, connecting to your mongo installation, and serving your application on port 3000:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ meteor
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; /path/to/testapp &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;

&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; Meteor server running on: http://localhost:3000/&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Instead, my terminal became quite upset about it:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; /path/to/testapp &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;

Unexpected mongo &lt;span class=&quot;token builtin class-name&quot;&gt;exit&lt;/span&gt; code &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;. Restarting.
Unexpected mongo &lt;span class=&quot;token builtin class-name&quot;&gt;exit&lt;/span&gt; code &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;. Restarting.
Unexpected mongo &lt;span class=&quot;token builtin class-name&quot;&gt;exit&lt;/span&gt; code &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;. Restarting.
Can&apos;t start mongod&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Whups! Everything seems normal in my mongo installation, but after a lot of searching I finally found the problem on &lt;a href=&quot;http://stackoverflow.com/questions/18505372/meteor-update-0-6-4-0-6-5-mongo-error&quot;&gt;stackoverflow&lt;/a&gt;. From among the answers I found this solution:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;I’m also getting this error on Ubuntu. As mentioned, it’s caused by mongo and mongod from ~/.meteor/tools/latest/mongodb/bin being compiled with an older version of glib. You can replace the version of mongo bundled by meteor with the version installed in your system:&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;cd&lt;/span&gt; ~/.meteor/tools/latest/mongodb/bin/
&lt;span class=&quot;token function&quot;&gt;mv&lt;/span&gt; mongo mongo-backup
&lt;span class=&quot;token function&quot;&gt;mv&lt;/span&gt; mongod mongod-backup
&lt;span class=&quot;token function&quot;&gt;ln&lt;/span&gt; -s /usr/bin/mongo
&lt;span class=&quot;token function&quot;&gt;ln&lt;/span&gt; -s /usr/bin/mongod&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Brilliant! Following these instructions, I was finally able to start meteor.&lt;/p&gt;
&lt;h3&gt;Getting down to business&lt;/h3&gt;
&lt;p&gt;Now to test out some of the awesome functionality of this framework. I &lt;a href=&quot;http://www.meteor.com/examples/todos&quot;&gt;followed an example&lt;/a&gt; and created a todo list:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ meteor create --example todos
$ &lt;span class=&quot;token builtin class-name&quot;&gt;cd&lt;/span&gt; todos
$ meteor deploy totally-fake-url.meteor.com
Deploying to totally-fake-url.meteor.com.  Bundling&lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;.
Uploading&lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;.
Now serving at totally-fake-url.meteor.com&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Playing around with creating new todos and lists, it is clear that data is being added and changed instantly and persistently.&lt;/p&gt;
&lt;p&gt;A Meteor application is a mix of JavaScript that runs inside a client web browser, JavaScript that runs on the Meteor server inside a Node.js container, and all the supporting HTML fragments, CSS rules, and static assets.&lt;/p&gt;
&lt;p&gt;I am really looking forward to diving further into &lt;a href=&quot;http://docs.meteor.com/#concepts&quot;&gt;the docs&lt;/a&gt; to learn more about this incredible framework.
AWESOME&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Partial to Ajax]]></title><description><![CDATA[I have been building a new project and getting creative with views. I am working with bootstrap and jquery to develop tabbed displays, and…]]></description><link>http://katieleonard.ca/blog/2013/2013-10-18-partial-to-ajax/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2013/2013-10-18-partial-to-ajax/</guid><pubDate>Sat, 19 Oct 2013 05:29:03 GMT</pubDate><content:encoded>&lt;p&gt;I have been building a new project and getting creative with views. I am working with bootstrap and jquery to develop tabbed displays, and in the process have been gleaning a deeper understanding of rails routes, controllers, and assets. Using Ajax to load partials into rails views is a three part process:&lt;/p&gt;
&lt;!--more--&gt;
&lt;h4&gt;1. In the View, Add a Link&lt;/h4&gt;
&lt;p&gt;/path/to/view.html.erb&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ruby&quot;&gt;&lt;pre class=&quot;language-ruby&quot;&gt;&lt;code class=&quot;language-ruby&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;%=&lt;/span&gt; link_to &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Show my partial&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; path_to_controller&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token symbol&quot;&gt;remote&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The key difference in the syntax for this link is “remote: true”, which signals to the controller action to respond using ajax, not html.&lt;/p&gt;
&lt;h4&gt;2. Create a Partial&lt;/h4&gt;
&lt;p&gt;/path/to/view/&lt;em&gt;my&lt;/em&gt;partial.html.erb&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ruby&quot;&gt;&lt;pre class=&quot;language-ruby&quot;&gt;&lt;code class=&quot;language-ruby&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;%=&lt;/span&gt; form_for &lt;span class=&quot;token variable&quot;&gt;@model&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt;f&lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;%&gt;
    &amp;lt;%= f.label :my_text_field, &quot;Text Field Label&quot; %&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;%=&lt;/span&gt; f&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;text_area &lt;span class=&quot;token symbol&quot;&gt;:my_text_field&lt;/span&gt; &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;%&gt;
    &amp;lt;%= f.submit &quot;New&quot;, class: &quot;btn btn-primary&quot; %&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;end&lt;/span&gt; &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;%&gt;
&amp;lt;/div&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h4&gt;3. In the Controller Action, Add a js Response&lt;/h4&gt;
&lt;p&gt;/path/to/controller.rb&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ruby&quot;&gt;&lt;pre class=&quot;language-ruby&quot;&gt;&lt;code class=&quot;language-ruby&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token method-definition&quot;&gt;&lt;span class=&quot;token function&quot;&gt;my_action&lt;/span&gt;&lt;/span&gt;
  respond_to &lt;span class=&quot;token keyword&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt;format&lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt;
    format&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;js
  &lt;span class=&quot;token keyword&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Normally, Rails will render the view that corresponds to the name of the action in response to an html request. The format.js line asks rails to look for a javascript file instead of an html file when it tries to render a view.&lt;/p&gt;
&lt;h4&gt;3. Create a my_action.js.erb File to Shape the Ajax Response&lt;/h4&gt;
&lt;p&gt;/path/to/view/my_action.js.erb&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token function&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;#your-placeholder-id&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;prepend&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;&amp;lt;%= escape_javascript(render &quot;path/to/view/my_partial&quot;&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Files with multiple extensions are processed from last to the first one. With js.erb, the erb will process all the ruby content first, and then the javascript will be run. Your js.erb file should be saved in the same folder as the rest of your controller’s views. This is an example :&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;app/views/users/
├── _my_partial.html.erb
├── edit.js.erb
├── show.html.erb&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Voila! When you click the link in your view the partial is loaded using Ajax.&lt;/p&gt;
&lt;p&gt;Awesome.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Rails, You Can Depend on Javascript]]></title><description><![CDATA[I am between computers at the moment, and I really really miss my OSX development environment. Dependency installation is so smooth and…]]></description><link>http://katieleonard.ca/blog/2013/2013-09-16-rails-depends-on-javascript/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2013/2013-09-16-rails-depends-on-javascript/</guid><pubDate>Tue, 17 Sep 2013 05:29:03 GMT</pubDate><content:encoded>&lt;p&gt;I am between computers at the moment, and I really really miss my OSX development environment. Dependency installation is so smooth and painless on mac, that I had quite forgotten the complications of setting up a complete environment in linux. For instance&lt;/p&gt;
&lt;h3&gt;Rails requires a javascript runtime environment&lt;/h3&gt;
&lt;p&gt;I am running an Ubuntu 9.4 remix on my little Atom Netbook. Getting rails up and running anew is a lesson in returning to fundamentals.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ gem &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; rails
$ rails new testapp -T
$ rails generate rspec:install
&lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;.
Could not &lt;span class=&quot;token function&quot;&gt;find&lt;/span&gt; a JavaScript runtime. See https://github.com/sstephenson/execjs &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; a list of available runtimes&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;!--more--&gt;
&lt;h3&gt;Why does rails use a javascript runtime?&lt;/h3&gt;
&lt;p&gt;A web application does not exist in a ruby/rails vacuum — rendering an html page requires css and javascript as well. By default, the ‘rails new’ command generates a Gemfile containing a few suggested goodies, including uglifier, which compresses javascript assets. Dealing with multiple layers of javascripts can hurt application performance, which is why rails has adopted a compression strategy. Uglifier minifies your javascript by removing all the whitespace.&lt;/p&gt;
&lt;p&gt;From the RailsGuides:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;You will need an ExecJS supported runtime in order to use uglifier. If you are using Mac OS X or Windows you have a JavaScript runtime installed in your operating system. Check the ExecJS documentation for information on all of the supported JavaScript runtimes.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;Setup Node.js on Linux&lt;/h3&gt;
&lt;p&gt;In Ubuntu 10.4 and above, a JavaScript runtime is included, but installing Node on an older Ubuntu distro is not as simple as&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ &lt;span class=&quot;token function&quot;&gt;sudo&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;apt-get&lt;/span&gt; nodejs&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I found the key sequence of commands on the Node.js website. First, update your packages and install node.js dependencies: python, g++, make, etc&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ &lt;span class=&quot;token function&quot;&gt;sudo&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;apt-get&lt;/span&gt; update
$ &lt;span class=&quot;token function&quot;&gt;sudo&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;apt-get&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; python-software-properties python g++ &lt;span class=&quot;token function&quot;&gt;make&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Next, add the location of the nodejs repository, update, and install.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ &lt;span class=&quot;token function&quot;&gt;sudo&lt;/span&gt; add-apt-repository ppa:chris-lea/node.js
$ &lt;span class=&quot;token function&quot;&gt;sudo&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;apt-get&lt;/span&gt; update
$ &lt;span class=&quot;token function&quot;&gt;sudo&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;apt-get&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; nodejs&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Wow — with all of that done, I can finally:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ rails generate rspec:install
      create  .rspec
      create  spec
      create  spec/spec_helper.rb&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Awesome.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Ruby Execution]]></title><description><![CDATA[I have started including an executable in my project setup. Many of the code challenges I have been practicing lately have included file I/O…]]></description><link>http://katieleonard.ca/blog/2013/2013-09-10-ruby-execution/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2013/2013-09-10-ruby-execution/</guid><pubDate>Wed, 11 Sep 2013 05:29:03 GMT</pubDate><content:encoded>&lt;p&gt;I have started including an executable in my project setup. Many of the code challenges I have been practicing lately have included file I/O, and while TDD and code exercising with RSpec is still my main process, developing a stand-alone fully-functional project requires something more.&lt;/p&gt;
&lt;!--more--&gt;
&lt;h3&gt;Blocks Code Challenge&lt;/h3&gt;
&lt;p&gt;I found the blocks code challenge on the &lt;a href=&quot;http://uva.onlinejudge.org/index.php?option=com_onlinejudge&amp;#x26;Itemid=8&amp;#x26;category=3&amp;#x26;page=show_problem&amp;#x26;problem=37&quot;&gt;UVa code competition website&lt;/a&gt;. To sum up, you have to write a program that will parse and carry out a series of commands for stacking blocks.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;move a onto b&lt;/li&gt;
&lt;li&gt;move a over b&lt;/li&gt;
&lt;li&gt;pile a onto b&lt;/li&gt;
&lt;li&gt;pile a over b&lt;/li&gt;
&lt;li&gt;quit&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The commands will be provided in an input file, and an output is specified. Fun problem, right? So, I start my project folder using my &lt;a href=&quot;http://www.katieleonard.ca/automation/2013/09/08/thor-sets-up-a-project/&quot;&gt;thor task&lt;/a&gt;, and work awhile adding logic and tests and data as appropriate. My file tree finishes like this:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;blocks
├── data
│   ├── input.txt
│   └── output.txt
├── lib
│   └── blocks.rb
├── spec
│   ├── blocks_spec.rb
│   └── spec_helper.rb
├── Gemfile
└── README.md&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;So, in order to use my script, I would have to call it from the command line:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ ruby lib/blocks.rb data/input.txt
&lt;span class=&quot;token comment&quot;&gt;#=&gt; or&lt;/span&gt;
$ data/input.txt &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; ruby lib/blocks.rb&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This is an extremely verbose way to deliver a final product, and I would much rather call $ blocks &amp;#x3C;file_input&gt;. It turns out that making an executable is easy and elegant, just like everything else in ruby. You just have to declare the ruby environment, include a few notes on usage, load the file tree, and call the class:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;#!/usr/bin/env ruby
# blocks
# 10-Sep-2013
#
# Usage:
# ./blocks data/input.txt
#
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), &apos;lib&apos;))
require &apos;blocks&apos;
Blocks.new.process_input&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Placing this code in a non-extension file, like ‘blocks’, in the main directory, I can make it an executable by changing the file permissions:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ &lt;span class=&quot;token function&quot;&gt;chmod&lt;/span&gt; +x ./blocks&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And I can call it like any other executable:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ ./blocks data/input.txt&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I liked this solution so much, I added it to my thor project setup! Oh, and if you are interested in seeing my solution for the blocks problem, checkout my &lt;a href=&quot;https://github.com/keighty/datastructures/tree/master/ruby/blocks&quot;&gt;github repo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Awesome.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Thor Sets Up A Project]]></title><description><![CDATA[A few weeks ago I posted about using Thor to generate system-wide notes files with a standard format. Since then, I have been doing a lot of…]]></description><link>http://katieleonard.ca/blog/2013/2013-09-08-thor-sets-up-a-project/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2013/2013-09-08-thor-sets-up-a-project/</guid><pubDate>Mon, 09 Sep 2013 05:29:03 GMT</pubDate><content:encoded>&lt;p&gt;A few weeks ago I posted about &lt;a href=&quot;http://www.katieleonard.ca/automation/2013/08/30/hammer-out-tasks-with-thor/&quot;&gt;using Thor to generate system-wide notes files with a standard format&lt;/a&gt;. Since then, I have been doing a lot of smaller code challenges, and I wanted to set up a Thor task for generating a standard project file tree.&lt;/p&gt;
&lt;!--more--&gt;
&lt;p&gt;My Goal Tree:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;project_name
├── lib
│   └── project_name.rb
├── spec
│   ├── project_name_spec.rb
│   └── spec_helper.rb
├── Gemfile
└── README.md&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I always begin with these files and this organization. A Gemfile and README are essential for setting up the environment and explaining the gist of the project. I am most comfortable with RSpec, and to get into the practice of TDD, setting up a testing environment right away is non-negotiable. All of these standard files contain some automatic content as well:&lt;/p&gt;
&lt;h5&gt;spec_helper.rb loads the library&lt;/h5&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), &apos;..&apos;, &apos;lib&apos;))
require &apos;rspec&apos;
require &apos;project_name&apos;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h5&gt;project&lt;em&gt;name&lt;/em&gt;spec.rb sets up the first test&lt;/h5&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;require &apos;spec_helper&apos;

describe ProjectName do
  before (:each) {  }
  subject {  }

  it &quot;should pass&quot;
end&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h5&gt;Gemfile specifies the right gems for setting up the project&lt;/h5&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;ruby &apos;2.0.0&apos;
gem &apos;rspec&apos;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;There are other files that could have auto-generated content as well, like a Rakefile, or a config.ru, but this is a good start.&lt;/p&gt;
&lt;h4&gt;Create a Thor task (rb_project.thor):&lt;/h4&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;#!/usr/bin/env ruby
require &quot;rubygems&quot;
require &quot;thor&quot;

class RbProject &amp;lt; Thor
  desc &quot;init&quot;, &quot;creates a ruby project with rspec&quot;

  def init(title=&quot;new_project&quot;)
    Dir.mkdir(title)
    Dir.chdir(title)
    Dir.mkdir(&quot;spec&quot;)
    Dir.mkdir(&quot;lib&quot;)
    filename = &quot;#{title}&quot;

    open(File.new(&quot;README.md&quot;, &quot;w&quot;), &quot;w&quot;) do |note|
      note.puts &quot;# #{title}&quot;
    end

    open(File.new(&quot;Gemfile&quot;, &quot;w&quot;), &quot;w&quot;) do |my_gem|
      my_gem.puts &quot;ruby &apos;2.0.0&apos;&quot;
      my_gem.puts &quot;gem &apos;rspec&apos;&quot;
    end

    open(File.new(&quot;spec/spec_helper.rb&quot;, &quot;w&quot;), &quot;w&quot;) do |spec|
      spec.puts &quot;$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), &apos;..&apos;, &apos;lib&apos;))&quot;
      spec.puts &quot;require &apos;rspec&apos;&quot;
      spec.puts &quot;require &apos;#{filename}&apos;&quot;
    end

    open(File.new(&quot;spec/#{filename}_spec.rb&quot;, &quot;w&quot;), &quot;w&quot;) do |spec|
      spec.puts &quot;require &apos;spec_helper&apos;&quot;
      spec.puts &quot;&quot;
      spec.puts &quot;describe #{camelize(filename)} do&quot;
      spec.puts &quot;  before (:each) {  }&quot;
      spec.puts &quot;  xit &apos;should pass&apos;&quot;
      spec.puts &quot;end&quot;
    end
  end

  private
    def camelize(snake)
      title = snake.split(&apos;_&apos;).each do |word|
        word.capitalize!
      end
      title.join(&apos;&apos;)
    end
end&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I created a private method camelize in order to change the snake_case project name into a CamelCase class name.&lt;/p&gt;
&lt;p&gt;As before, I install my thor task system wide:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ thor &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; rb_project.thor&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And now my project generation task can be run from any directory, anywhere on my system:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ thor list
note
----
thor note:create  &lt;span class=&quot;token comment&quot;&gt;# creates a notes file in markdown&lt;/span&gt;

rb_project
----------
thor rb_project:init  &lt;span class=&quot;token comment&quot;&gt;# creates a ruby project with rspec&lt;/span&gt;

$ thor rb_project:init test_project
$ tree test_project/
test_project/
├── lib
│   └── test_project.rb
├── spec
│   ├── spec_helper.rb
│   └── test_project_spec.rb
├── Gemfile
├── README.md

&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt; directories, &lt;span class=&quot;token number&quot;&gt;6&lt;/span&gt; files&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Awesome.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[ARGF all you want]]></title><description><![CDATA[Many of the fun, junior code challenges I have encountered deal a lot with input/output of data, and I found a great ruby feature that…]]></description><link>http://katieleonard.ca/blog/2013/2013-09-05-argf-all-you-want/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2013/2013-09-05-argf-all-you-want/</guid><pubDate>Fri, 06 Sep 2013 05:29:03 GMT</pubDate><content:encoded>&lt;p&gt;Many of the fun, junior code challenges I have encountered deal a lot with input/output of data, and I found a great ruby feature that provides flexibility at the command line.&lt;/p&gt;
&lt;!--more--&gt;
&lt;h3&gt;Data Input&lt;/h3&gt;
&lt;p&gt;There are a lot of ways to treat data at the command line, but the one I was most familiar with is passing in a filename as an argument:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ ruby example_script.rb file1.csv file2.csv &lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;.
$ ruby example_script.rb file1.csv &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;more&lt;/span&gt;
$ ruby example_script.rb file1.csv &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; output.txt&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;Filename Input&lt;/h3&gt;
&lt;p&gt;Using ARGV, we can access the list of filenames provided at the command line. ARGV is an array containing all the information that follows the command. For example:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ example_command apple banana orange
&lt;span class=&quot;token comment&quot;&gt;# ARGV = [&quot;apple&quot;, &quot;banana&quot;, &quot;orange&quot;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;One can process each filename in ARGV using regular array methods:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ruby&quot;&gt;&lt;pre class=&quot;language-ruby&quot;&gt;&lt;code class=&quot;language-ruby&quot;&gt;&lt;span class=&quot;token constant&quot;&gt;ARGV&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;each&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt;arg&lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt;
  process_string&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;read&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;arg&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;File.read(arg) reads the file into a “\n” delimited string, which can be processed further. If there are no arguments, ARGV is an empty array.&lt;/p&gt;
&lt;h3&gt;Piped Input&lt;/h3&gt;
&lt;p&gt;Say that we want to enter data directly into a program rather than use a fixed filename at the command line — a useful technique for when we want data to flow out of one process and into another:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ &lt;span class=&quot;token function&quot;&gt;cat&lt;/span&gt; file1.csv &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; ruby example_script.rb
$ &lt;span class=&quot;token function&quot;&gt;cat&lt;/span&gt; *.csv &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; ruby example_script.rb
$ ruby example_script.rb &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; file1.csv&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Using the pipe, ”|” or ”&amp;#x3C;”, we can push a string of data from one process into another, but what happens to our program when we try to do this?&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ example.csv &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; ruby example_script.rb
TypeError: can`t convert nil into String&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We get a TypeError! Recall that command line arguments are stored in ARGV, but we are not providing any command line arguments. ARGV is an empty array, and we are attempting to open a file from ARGV[0] = nil. Shame on us! How do we access data that is piped in as well as data that is appended to the command line? Do we have to check for the source of the data before we can treat it? Turns out, we DON’T.&lt;/p&gt;
&lt;h3&gt;The ARGF Solution&lt;/h3&gt;
&lt;p&gt;Ruby has a nifty interface for handling data input, regardless of whether it arrives as a command line argument or from another data source. We can replace the code we wrote earlier with a single line:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ruby&quot;&gt;&lt;pre class=&quot;language-ruby&quot;&gt;&lt;code class=&quot;language-ruby&quot;&gt;process_string&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;ARGF&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;read&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;If ARGV is not empty, ARGF will assume it is an array of filenames and will treat them accordingly. If ARGV is empty, it will read from $stdin to get the data passed in via the pipe. One caveat is that you can’t read from both ARGV and the pipe: if ARGV != [  ], $stdin is ignored.&lt;/p&gt;
&lt;p&gt;Awesome.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Hammer-out Tasks with Thor]]></title><description><![CDATA[A few months ago I gave a small lightning talk to my code school class about automating tasks using Rake. Before I learned ruby I used bash…]]></description><link>http://katieleonard.ca/blog/2013/2013-08-30-hammer-out-tasks-with-thor/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2013/2013-08-30-hammer-out-tasks-with-thor/</guid><pubDate>Sat, 31 Aug 2013 05:29:03 GMT</pubDate><content:encoded>&lt;p&gt;A few months ago I gave a small lightning talk to my code school class about automating tasks using &lt;a href=&quot;http://rake.rubyforge.org/&quot;&gt;Rake&lt;/a&gt;. Before I learned ruby I used bash scripts to accomplish similar things, but was often bogged down in learning the syntax of string-processing essentials like awk or sed. I wished for the simplicity of Ruby, and thought that Rake was the bees-knees. After my talk, &lt;a href=&quot;chuckvose.com&quot;&gt;Chuck&lt;/a&gt;, my PCS mentor, put together a repo of &lt;a href=&quot;http://whatisthor.com/&quot;&gt;Thor&lt;/a&gt; tasks that accomplished the same tasks but could be installed system wide.&lt;/p&gt;
&lt;!--more--&gt;
&lt;h3&gt;&lt;a href=&quot;http://whatisthor.com/&quot;&gt;Thor&lt;/a&gt; is my new hero&lt;/h3&gt;
&lt;p&gt;Unlike Rake tasks, which are confined to the directory containing the Rakefile, Thor tasks can be installed on your system and called from anywhere. My note files are all formatted in a particular way. Before Thor, I used a rake task:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ &lt;span class=&quot;token builtin class-name&quot;&gt;cd&lt;/span&gt; notesDirWithRakefile
$ rake post &lt;span class=&quot;token assign-left variable&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;new post title&quot;&lt;/span&gt;
$ Creating new post: &lt;span class=&quot;token string&quot;&gt;&quot;./130830_new_post_title&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The Rake task auto-formats the filename, replacing spaces with underscores, and prepends today’s date so that they will sort in the order they are made. This worked great for when I wanted to keep notes in that one folder, but later I wanted to be able to keep notes on a particular project. I would either have to copy the Rakefile (two places to update if I made any changes), or create a symbolic link (which would break if I ever moved my Rakefile). Neither of these options seemed to be the most practical. Enter Thor:&lt;/p&gt;
&lt;p&gt;Creating the Thor task is as easy as pie:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;require &apos;thor&apos;

class Note &amp;lt; Thor
  desc &quot;create&quot;, &quot;creates a notes file in markdown&quot;
  def create(title=&quot;new note&quot;)
    slug = title.downcase.strip.gsub(&apos; &apos;, &apos;_&apos;).gsub(/[^\w-]/, &apos;&apos;)
    date = Time.parse(Time.now).strftime(&apos;%y%m%d&apos;)
    filename = File.join(&quot;./&quot;, &quot;#{date}_#{slug}.md&quot;)

    if File.exist?(filename)
      abort(&quot;rake aborted!&quot;) if ask(&quot;#{filename} already exists. Do you want to overwrite?&quot;, [&apos;y&apos;, &apos;n&apos;]) == &apos;n&apos;
    end

    puts &quot;Creating new post: #{filename}&quot;
    open(filename, &apos;w&apos;) do |post|
      post.puts &quot;# #{title.gsub(/-/,&apos; &apos;).capitalize}&quot;
    end
  end
end&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Listing all Thor tasks is easy:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ thor list
note
----
thor note:create  &lt;span class=&quot;token comment&quot;&gt;# creates a notes file in markdown&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Installing a Thor task for system use is easy:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ thor &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; notes.thor
&lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;.
Do you wish to &lt;span class=&quot;token builtin class-name&quot;&gt;continue&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;y/N&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;? y
Please specify a name &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; notes.thor &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; the system repository &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;notes.thor&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;: note
Storing thor &lt;span class=&quot;token function&quot;&gt;file&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; your system repository&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Uninstalling a Thor task is easy:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ thor uninstall note
Uninstalling note.
Done.&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;With my Thor notes task installed system-wide, I can create a note page in any directory, for any reason, without copying code.&lt;/p&gt;
&lt;p&gt;Awesome.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Serving Some Java]]></title><description><![CDATA[For a recent java coding challenge I was asked, among other things, to make a server. It has been several years since I last attempted it…]]></description><link>http://katieleonard.ca/blog/2013/2013-08-24-serving-some-java/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2013/2013-08-24-serving-some-java/</guid><pubDate>Sun, 25 Aug 2013 05:29:03 GMT</pubDate><content:encoded>&lt;p&gt;For a recent java coding challenge I was asked, among other things, to make a server. It has been several years since I last attempted it, and I had forgotten how easy it could be.&lt;/p&gt;
&lt;!--more--&gt;
&lt;h4&gt;Server&lt;/h4&gt;
&lt;p&gt;A server, like any good conversationalist, is a good listener. A server is a program running on a computer that listens at a port, waiting to receive instructions.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;public class Server {
  private static String inputLine;

  public static void main(String[] args) {

    private static final int PORT_NUMBER = 63400

    try {
      // Socket variables
      ServerSocket serverSocket = new ServerSocket(PORT_NUMBER);
      Socket clientSocket = serverSocket.accept();

      // IO variables
      InputStreamReader inputReader = new InputStreamReader(clientSocket.getInputStream());
      BufferedReader bReader = new BufferedReader(inputReader);

      while ((inputLine = bReader.readLine()) != null) {
        System.out.println(inputLine);
      }

    } catch (Exception e) {
      System.out.println(e);
    }
  }
}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The server opens a socket on a specified port (in this case, port 63400). A socket is the point at which two-way communication happens between computer programs. The server opens a socket at a port and waits for a client to bind the socket so they can exchange information. It waits for input from the client, with instructions to print out anything the client puts in (line 18). So where is the client?&lt;/p&gt;
&lt;h4&gt;Client&lt;/h4&gt;
&lt;p&gt;The client is even simpler than the server: it finds the server at the specified port and connects to the socket.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;public class Client {

  private static final int PORT_NUMBER = 63400

  public static void main(String[] args) {

    try {

      // Socket variables
      Socket socket = new Socket(&quot;localhost&quot;, PORT_NUMBER);
      PrintWriter pWriter = new PrintWriter(socket.getOutputStream(), true);

      pWriter.println(&quot;Hello World!&quot;);

    } catch (Exception e) {
      System.out.println(e);
    }
  }
}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;With a successful connection, it generates an output stream. If you start the server in one console it will look like it isn’t doing anything, but when you start the client in another console you can watch them communicate. The client writes “Hello World” directly into the port where the server is listening (socket.getOutputStream()), and as instructed, the server obediently prints “Hello World” to the console.&lt;/p&gt;
&lt;p&gt;Awesome.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Runtime For Your Life]]></title><description><![CDATA[Eh? is coming along as a functioning interpreted language, but we are still missing a runtime. We have a lexer that chops and tags our code…]]></description><link>http://katieleonard.ca/blog/2013/2013-08-19-runtime-for-your-life/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2013/2013-08-19-runtime-for-your-life/</guid><pubDate>Tue, 20 Aug 2013 05:29:03 GMT</pubDate><content:encoded>&lt;p&gt;Eh? is coming along as a functioning interpreted language, but we are still missing a runtime. We have a lexer that chops and tags our code string into tokens, and a grammar that contains the rules for order of operations, and a parser that is generated by RACC from the grammar. The parser assembles the tokens into an evaluation tree (AST), but we need a runtime to do the actual evaluation.&lt;/p&gt;
&lt;!--more--&gt;
&lt;p&gt;Recall from my previous post that the AST consists of nodes, like this one for a method definition:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;class DefNode
  def initialize(name, params, body)
    @name = name
    @params = params
    @body = body
  end

  def eval(context)
    context.current_class.can_methods[@name] = CanMethod.new(@params, @body)
  end
end&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;When a method definition node is evaluated it adds a new entry to the can_methods hash. The name of the method is its key, and the value is an object (CanMethod.new) that contains the details of method evaluation (parameters and the method body). The context is the scope of the evaluation - in the case of a method call, the context is the enclosing class.&lt;/p&gt;
&lt;p&gt;Ok, so when does the CanMethod get evaluated? It happens at runtime. A class node is built and all the method definitions are added, but the node tree will remain untouched until until a method is called.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;class CanMethod
  def initialize(params, body)
    @params = params
    @body = body
  end

  def call(receiver, arguments)
    @body.eval(Context.new(receiver))
  end
end&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;When your program calls a method, a portion of the AST is evaluated. The body of the method object is called with the provided parameters in the context of the method receiver. For ruby newbies, the receiver is the object on the left side of the method call — ie. in foo.bar(3), foo is the receiver and bar is called with the parameter of 3 in the context of foo.  The runtime will create a new context for the method (recall that ruby is block scoped, meaning that all variables and blocks within the method are confined to that method… mostly).&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;class Context
  attr_reader :locals, :current_self, :current_class

  @@constants = {}

  def initialize(current_self, current_class=current_self.can_class)
    @locals = {}
    @current_self = current_self
    @current_class = current_class
  end
end&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The context contains all the local variables for the scope as well as a reference to what object is self, and which is super. We are getting very close to putting all these pieces together!&lt;/p&gt;
&lt;p&gt;Awesome&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Parcel Parser]]></title><description><![CDATA[On the last episode, I described how to label chunks of code for processing through a parser. Strings are labeled as ‘STRING’, class…]]></description><link>http://katieleonard.ca/blog/2013/2013-08-16-parcel-parser/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2013/2013-08-16-parcel-parser/</guid><pubDate>Sat, 17 Aug 2013 05:29:03 GMT</pubDate><content:encoded>&lt;p&gt;On the last episode, I described how to label chunks of code for processing through a parser. Strings are labeled as ‘STRING’, class definitions as ‘A’ + ‘CONSTANT’, etc.&lt;/p&gt;
&lt;h2&gt;What is a parser?&lt;/h2&gt;
&lt;p&gt;A parser separates and analyzes a piece of text according to a set of rules specified by a formal grammar. The analysis is performed by assembling the tokenized code into an Abstract Syntax Tree (AST) - a tree of nodes that represent what the code means to the language. The AST evaluates the nodes in a similar manner to order of operations in math: each token is placed on the evaluation tree, and expressions are evaluated by reducing each branch in order.&lt;/p&gt;
&lt;p&gt;The parser itself is can be written by hand, but I am using RACC: an LALR (Look Ahead, Left to right, Reverse) parser written by &lt;a href=&quot;https://github.com/tenderlove/racc&quot;&gt;tenderlove&lt;/a&gt; to generate Ruby programs. How do we specify a grammar that RACC will understand?&lt;/p&gt;
&lt;!--more--&gt;
&lt;p&gt;Each rule is formatted in the following way:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;RuleName:
  OtherRule TOKEN AnotherRule    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; code to run &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; OtherRule                      &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;. &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;It is similar to an if/else statement that captures all possible expressions beginning with the most specific (ie: an expression with TWO rules matches line 2) to more general (all other single expressions are captured on line 3). When a token matches a rule, the code in the attached code block is run.&lt;/p&gt;
&lt;p&gt;The code blocks correspond to instructions on how to treat matching tokens. For example, the grammar should specify what happens when the code contains a class definition, labeled with ‘A’ + ‘CONSTANT’.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;...
# Class definition
Class:
  A CONSTANT Block { result = ClassNode.new(val[1], val[2]) }
;
...&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;When the parser catches a class token it will create a new ClassNode with the class name (CONSTANT) and the block as arguments. The val[] array refers to the grammar rule [A, CONSTANT, Block].&lt;/p&gt;
&lt;p&gt;Some tokens are parsed very close to AS IS:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;Literal:
  NUMBER { result = LiteralNode.new(val[0]) }
| STRING { result = LiteralNode.new(val[0]) }
| TRUE   { result = LiteralNode.new(true) }
| FALSE  { result = LiteralNode.new(false) }
| NIL    { result = LiteralNode.new(nil) }
;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Each literal triggers the creation of a new LiteralNode with its value as the only argument.&lt;/p&gt;
&lt;p&gt;The Nodes are outlined in a Nodes class, where the rules of evaluation are defined.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;...
class ClassNode
  def initialize(name, body)
    @name = name
    @body = body
  end

  def eval(context)
    eh_class = CanadianClass.new
    context[@name] = eh_class
    @body.eval(Context.new(eh_class, eh_class))
    eh_class
  end
end
...&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;A ClassNode is initialized with two params (recall from the grammar: ClassNode.new(val[1], val[2])), the class name and its code block. The context is like scope - it can hold modules, classes, methods, attributes, aliases, requires, and includes. Classes, modules, and files are all Contexts (definition from &lt;a href=&quot;http://ruby-doc.org/stdlib-1.8.6/libdoc/rdoc/rdoc/RDoc/Context.html&quot;&gt;Rdocs&lt;/a&gt;). Evaluation of a ClassNode begins by assigning the class to a context and evaluating the code block, which adds more contexts. In this way, a tree structure is formed - an AST - which does all the interpreting work for the new language.&lt;/p&gt;
&lt;p&gt;When the grammar and node definitions are complete, RACC will generate a parser:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ racc -vo parser.rb grammar.y&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The parser is a relatively obtuse set of methods and state transition tables, and when you run code through the parser you get an AST that follows the grammar you have defined.&lt;/p&gt;
&lt;p&gt;So, now I have a lexer and a parser, but I still can’t run my code. I need to define a runner class that will put all these parts together, but first, I need a break.&lt;/p&gt;
&lt;p&gt;Awesome.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Flex Your Lexer]]></title><description><![CDATA[A Lexer is a ruby class with a single method: tokenize(). Its purpose is to label each chunk of code with a particular token. Strings are…]]></description><link>http://katieleonard.ca/blog/2013/2013-08-15-flex-your-lexer/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2013/2013-08-15-flex-your-lexer/</guid><pubDate>Fri, 16 Aug 2013 05:29:03 GMT</pubDate><content:encoded>&lt;p&gt;A Lexer is a ruby class with a single method: tokenize(). Its purpose is to label each chunk of code with a particular token. Strings are labeled as strings, numbers as numbers, and class names as constants. For example,&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;Lexer.new.tokenize(&quot;string&quot;)
# =&gt;[[:STRING, &quot;string&quot;]]
Lexer.new.tokenize(&quot;True&quot;)
# =&gt;[[:CONSTANT, &quot;True&quot;]]
Lexer.new.tokenize(&quot;a Car&quot;)
# =&gt;[[:A, &apos;a&apos;], [:CONSTANT, &apos;Car&apos;]])
Lexer.new.tokenize(&quot;+&quot;)
# =&gt;[[&quot;+&quot;, &quot;+&quot;]]&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;“Lexing” is accomplished using regular expressions. The lexer treats the text string of your code like a shish kabob - it slides recognizable chunks off the skewer one at a time and categorizes them (onion, pepper, method definition, etc).&lt;/p&gt;
&lt;!--more--&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;class Lexer
  KEYWORDS = [&apos;a&apos;, &apos;can&apos;, &apos;if&apos;, &apos;else&apos;, &apos;while&apos;, &apos;true&apos;, &apos;false&apos;, &apos;nil&apos;]

  def tokenize(code)
    code.chomp!
    i = 0
    tokens = []

    while i &amp;lt; code.size
      chunk = code[i..-1]

      # checks keywords
      if identifier = chunk[/\A(eh\?)/, 1]
        tokens &amp;lt;&amp;lt; [&apos;}&apos;, &apos;}&apos;]
        i += identifier.size

      elsif identifier = chunk[/\A([a-z]\w*)/, 1]
        if KEYWORDS.include?(identifier)
          tokens &amp;lt;&amp;lt; [identifier.upcase.to_sym, identifier]
        else
          tokens &amp;lt;&amp;lt; [:IDENTIFIER, identifier]
        end
        i += identifier.size
...&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In this example lexer I have defined my list of keywords, removed the trailing newline, and begun peeling identifiable chunks off the code example.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;If the code chunk matches an ‘eh?’ it will add a closing brace to the token array.&lt;/li&gt;
&lt;li&gt;If the code chunk matches a KEYWORD it will be upcased and labeled as a keyword and added to the token array.&lt;/li&gt;
&lt;li&gt;If the code chunk matches any word of lowercase letters it will be labeled as an IDENTIFIER and added to the token array.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I continued defining regex rules until I was able to completely tokenize a class definition:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;code = &amp;lt;&amp;lt;-EOS
a Canadian
  can curl
    if skip:
      say &apos;Hurry!&apos;
    eh?
  eh?
eh?
EOS
...
Lexer.new.tokenize(code)
# =&gt; [[:A, &quot;a&quot;], [:CONSTANT, &quot;Canadian&quot;], [:CAN, &quot;can&quot;], [:IDENTIFIER, &quot;curl&quot;], [:IF, &quot;if&quot;], [:IDENTIFIER, &quot;skip&quot;], [&quot;{&quot;, &quot;{&quot;], [:IDENTIFIER, &quot;say&quot;], [:STRING, &quot;Hurry!&quot;], [&quot;}&quot;, &quot;}&quot;], [&quot;}&quot;, &quot;}&quot;], [&quot;}&quot;, &quot;}&quot;]]&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now that I have an array of tokens, it is time to write my grammar laws that will tell the parser what to do with them.&lt;/p&gt;
&lt;p&gt;Awesome&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Canadian Flair]]></title><description><![CDATA[For my last month at code school, I have decided to learn what it takes to develop a new programming language. Having been teased for my…]]></description><link>http://katieleonard.ca/blog/2013/2013-08-10-canadian-flair/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2013/2013-08-10-canadian-flair/</guid><pubDate>Sun, 11 Aug 2013 05:29:03 GMT</pubDate><content:encoded>&lt;p&gt;For my last month at code school, I have decided to learn what it takes to develop a new programming language. Having been teased for my Canadian accent, I thought it appropriate to incorporate some idiomatic Canadianisms, and call my language Eh? Deciding what actual features I want to implement in my programming language is an interesting task, and I think I have narrowed it down to a couple of standard rules and a couple wacky ones:&lt;/p&gt;
&lt;h3&gt;Rules for Eh?&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;blocks of code are delimited by ’:’ and ‘eh?’&lt;/li&gt;
&lt;li&gt;classes are declared using “A” keyword&lt;/li&gt;
&lt;li&gt;methods are defined using “CAN” keyword&lt;/li&gt;
&lt;li&gt;lowercase identifiers are local variables or method names&lt;/li&gt;
&lt;li&gt;capitalized identifiers are global variables&lt;/li&gt;
&lt;li&gt;no parens for args&lt;/li&gt;
&lt;li&gt;last value evaluated in return value&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;everything is an object&lt;/p&gt;
&lt;!--more--&gt;
&lt;h1&gt;Steps for building an interpreted language&lt;/h1&gt;
&lt;/li&gt;
&lt;li&gt;This code has to be provided as input to a lexer.&lt;/li&gt;
&lt;li&gt;The lexer will convert that input into tokens.&lt;/li&gt;
&lt;li&gt;The parser will organize those tokens into a tree of nodes.&lt;/li&gt;
&lt;li&gt;The runtime will evaluate the nodes using ruby.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Prototype&lt;/h3&gt;
&lt;p&gt;Here is what I would like the final result to look like:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;a Canadian
  with toque
  with scarf
  with broom

  can curl
    if skip:
      say &quot;Hurry!&quot;
    eh?
    if lead:
      pass
    eh?
    say &quot;How social the game...&quot;
  eh?

  can say_aboot:
    say &quot;What&apos;s it all aboot?&quot;
  eh?
eh?&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;With this vague action plan and &lt;a href=&quot;http://createyourproglang.com/?hop=rubyinside&quot;&gt;“Create Your Own Programming Language”&lt;/a&gt; by Marc-Andre Cournoyer in hand, off we go!&lt;/p&gt;
&lt;p&gt;Awesome&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Show-off with GitHub and Docco]]></title><description><![CDATA[I was experimenting with some documentation styles today and discovered two bits of gold: gh-pages and docco: Creating a site for your…]]></description><link>http://katieleonard.ca/blog/2013/2013-08-06-show-off-with-github/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2013/2013-08-06-show-off-with-github/</guid><pubDate>Wed, 07 Aug 2013 05:29:03 GMT</pubDate><content:encoded>&lt;p&gt;I was experimenting with some documentation styles today and discovered two bits of gold: gh-pages and docco&lt;!--more--&gt;:&lt;/p&gt;
&lt;p&gt;Creating a site for your project using GitHub is a 3 step process:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;create a new orphan branch called gh-pages&lt;/li&gt;
&lt;li&gt;remove all the contents&lt;/li&gt;
&lt;li&gt;fill the branch with your boastful new site&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ &lt;span class=&quot;token builtin class-name&quot;&gt;cd&lt;/span&gt; repository

$ &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; checkout --orphan gh-pages
&lt;span class=&quot;token comment&quot;&gt;# Creates a branch, without any parents&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# Switched to a new branch &apos;gh-pages&apos;&lt;/span&gt;

$ &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;rm&lt;/span&gt; -rf &lt;span class=&quot;token builtin class-name&quot;&gt;.&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# Remove all files from the old working tree&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;From here you can use the &lt;a href=&quot;https://help.github.com/articles/creating-pages-with-the-automatic-generator&quot;&gt;GitHub Automatic Page generator&lt;/a&gt; to throw up a theme and some standard content, you can roll out a &lt;a href=&quot;http://jekyllbootstrap.com/&quot;&gt;jekyll bootstrap&lt;/a&gt; platform with blogging integration, or you can simply:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ &lt;span class=&quot;token builtin class-name&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Hello gh-pages!&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; index.html
$ &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt; index.html
$ &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; commit -a -m &lt;span class=&quot;token string&quot;&gt;&quot;First pages commit&quot;&lt;/span&gt;
$ &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; push origin gh-pages&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Add and commit your content to your gh-pages branch, and GitHub will generate what needs to be generated in order to serve your website.&lt;/p&gt;
&lt;p&gt;Your pages are hosted for free by GitHub. If you have already configured a personal site using &lt;a href=&quot;https://help.github.com/articles/user-organization-and-project-pages&quot;&gt;User Pages&lt;/a&gt;, your project pages will hang off the end of your domain like this : username.github.io/repo_name&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;http://jashkenas.github.io/docco/&quot;&gt;Docco&lt;/a&gt;&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;Docco is a quick-and-dirty documentation generator, written in Literate CoffeeScript. It produces an HTML document that displays your comments intermingled with your code. All prose is passed through Markdown, and code is passed through Highlight.js syntax highlighting.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Docco works with  Python, Ruby, JavaScript, Java, and many other languages, with no configuration — just plug and play!&lt;/p&gt;
&lt;p&gt;Install Docco with npm:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;sudo&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;npm&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; -g docco&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Run it against your code:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;docco lib&lt;span class=&quot;token comment&quot;&gt;/*.ruby&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Docco will create a docs/ folder in your project and will generate an html file for each ruby file in the lib directory. This is where beautifully commented code really pays off, but docco does not format multi-line code the same way. Check out my &lt;a href=&quot;http://www.katieleonard.ca/PCSnotes/docs/benchmark.html&quot;&gt;benchmark.rb&lt;/a&gt; for an example of how each comment style is treated by docco.&lt;/p&gt;
&lt;p&gt;TADA&lt;/p&gt;</content:encoded></item><item><title><![CDATA[State of the QuickUnion]]></title><description><![CDATA[In my last look at the UnionFind algorithm I made a quick-find implementation — finding if two elements were connected was fast but…]]></description><link>http://katieleonard.ca/blog/2013/2013-08-04-state-of-the-quickunion/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2013/2013-08-04-state-of-the-quickunion/</guid><pubDate>Mon, 05 Aug 2013 05:29:03 GMT</pubDate><content:encoded>&lt;p&gt;In my last look at the UnionFind algorithm I made a quick-find implementation — finding if two elements were connected was fast but connecting two elements was slow. The union operation is a good candidate for optimization.&lt;/p&gt;
&lt;!--more--&gt;
&lt;h1&gt;Quick Union&lt;/h1&gt;
&lt;p&gt;One way to optimize the union operation is to reduce the number of array accesses required.&lt;/p&gt;
&lt;p&gt;In QuickFind, the sets are arranged in a flat array of elements which all share the same value: they are all wearing the same t-shirt. When we connect elements from different sets, we must make sure that every element in the first set changes its t-shirt to match the elements in the other set. This is a time-consuming process, and uses a lot of t-shirts.&lt;/p&gt;
&lt;p&gt;What if only one element had to change its t-shirt? If the set had a single element in charge - a root - then joining elements from different sets would require identifying the t-shirt of the one in charge, and then changing to that element’s t-shirt.&lt;/p&gt;
&lt;p&gt;Using an array instead of t-shirts to keep track of the values, we can walk through what this implementation would look like:&lt;/p&gt;
&lt;table class=&quot;table table-bordered&quot;&gt;
  &lt;tr&gt;
    &lt;th&gt;Index&lt;/th&gt;
    &lt;td&gt;1&lt;/td&gt;
    &lt;td&gt;2&lt;/td&gt;
    &lt;td&gt;3&lt;/td&gt;
    &lt;td&gt;4&lt;/td&gt;
    &lt;td&gt;5&lt;/td&gt;
    &lt;td&gt;6&lt;/td&gt;
    &lt;td&gt;7&lt;/td&gt;
    &lt;td&gt;8&lt;/td&gt;
    &lt;td&gt;9&lt;/td&gt;
    &lt;td&gt;0&lt;/td&gt;
    &lt;th&gt;&lt;/th&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;th&gt;Value&lt;/th&gt;
    &lt;td&gt;1&lt;/td&gt;
    &lt;td&gt;2&lt;/td&gt;
    &lt;td&gt;3&lt;/td&gt;
    &lt;td&gt;4&lt;/td&gt;
    &lt;td&gt;5&lt;/td&gt;
    &lt;td&gt;6&lt;/td&gt;
    &lt;td&gt;7&lt;/td&gt;
    &lt;td&gt;8&lt;/td&gt;
    &lt;td&gt;9&lt;/td&gt;
    &lt;td&gt;0&lt;/td&gt;
    &lt;td&gt; | Each element begins as the root of its own set&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;th&gt;union(4,9)&lt;/th&gt;
    &lt;td&gt;1&lt;/td&gt;
    &lt;td&gt;2&lt;/td&gt;
    &lt;td&gt;3&lt;/td&gt;
    &lt;td class=&quot;highlight&quot;&gt;9&lt;/td&gt;
    &lt;td&gt;5&lt;/td&gt;
    &lt;td&gt;6&lt;/td&gt;
    &lt;td&gt;7&lt;/td&gt;
    &lt;td&gt;8&lt;/td&gt;
    &lt;td class=&quot;highlight&quot;&gt;9&lt;/td&gt;
    &lt;td&gt;0&lt;/td&gt;
    &lt;td&gt; | root(9) = 9, root(4) = 4, change array[4] = 9&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;th&gt;union(2,4)&lt;/th&gt;
    &lt;td&gt;1&lt;/td&gt;
    &lt;td class=&quot;highlight&quot;&gt;9&lt;/td&gt;
    &lt;td&gt;3&lt;/td&gt;
    &lt;td class=&quot;highlight&quot;&gt;9&lt;/td&gt;
    &lt;td&gt;5&lt;/td&gt;
    &lt;td&gt;6&lt;/td&gt;
    &lt;td&gt;7&lt;/td&gt;
    &lt;td&gt;8&lt;/td&gt;
    &lt;td&gt;9&lt;/td&gt;
    &lt;td&gt;0&lt;/td&gt;
    &lt;td&gt; | root(4) = 9, root(2) = 2, change array[2] = 9&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;th&gt;union(4,7)&lt;/th&gt;
    &lt;td&gt;1&lt;/td&gt;
    &lt;td&gt;9&lt;/td&gt;
    &lt;td&gt;3&lt;/td&gt;
    &lt;td  class=&quot;highlight&quot;&gt;9&lt;/td&gt;
    &lt;td&gt;5&lt;/td&gt;
    &lt;td&gt;6&lt;/td&gt;
    &lt;td  class=&quot;highlight&quot;&gt;7&lt;/td&gt;
    &lt;td&gt;8&lt;/td&gt;
    &lt;td&gt;7&lt;/td&gt;
    &lt;td&gt;0&lt;/td&gt;
    &lt;td&gt; | root(7) = 7, root(4) = 9, change array[9] = 7&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;th&gt;find(2,7)&lt;/th&gt;
    &lt;td&gt;1&lt;/td&gt;
    &lt;td class=&quot;highlight&quot;&gt;9&lt;/td&gt;
    &lt;td&gt;3&lt;/td&gt;
    &lt;td&gt;9&lt;/td&gt;
    &lt;td&gt;5&lt;/td&gt;
    &lt;td&gt;6&lt;/td&gt;
    &lt;td class=&quot;highlight&quot;&gt;7&lt;/td&gt;
    &lt;td&gt;8&lt;/td&gt;
    &lt;td class=&quot;highlight&quot;&gt;7&lt;/td&gt;
    &lt;td&gt;0&lt;/td&gt;
    &lt;td&gt; | root(7) = 7, root(2) = 7. The two are connected &lt;/td&gt;
  &lt;/tr&gt;
&lt;/table&gt;
&lt;h2&gt;QuickUnion&lt;/h2&gt;
&lt;p&gt;Again following the basic API:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;public class UF
---------------
public UF(int N)
public int find(int p, int q)
public void union(int p, int q)&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I adapted the QuickUnion in ruby:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;class QuickUnion
  def initialize(size)
    @find_array = Array.new(size){ |index| index }
  end

  # check if p and q have the same root
  def find(p, q)
    verify(p, q)
    root(p) == root(q)
  end

  # set id of p&apos;s root to the id of q&apos;s root
  def union(p, q)
    verify(p, q)
    @find_array[root(p)] = root(q)
  end

  private
    def root(index)
      # get root until root(index) == index
      if @find_array[index] == index
        return index
      else
        root(@find_array[index])
      end
    end

    def verify(p, q)
      raise NotAnElement if @find_array[p].nil?
      raise NotAnElement if @find_array[q].nil?
    end
end

class NotAnElement &amp;lt; Exception
end&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This implementation is a QuickUnion because in an array of 1,000,000 entries, connecting element p to element q is easy: you only have to find the root of p, and then change q to match (one root() and one array access). Finding if p and q are connected takes a little bit longer, because you have to perform two root operations: one for p and one for q, but it is still faster than accessing every element in the array.&lt;/p&gt;
&lt;h2&gt;Benchmark&lt;/h2&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ ruby lib/benchmark.rb
&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; Array Size: &lt;span class=&quot;token number&quot;&gt;100&lt;/span&gt;
       user     system      total        real
   &lt;span class=&quot;token number&quot;&gt;0.000000&lt;/span&gt;   &lt;span class=&quot;token number&quot;&gt;0.000000&lt;/span&gt;   &lt;span class=&quot;token number&quot;&gt;0.000000&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;  &lt;span class=&quot;token number&quot;&gt;0.001865&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
   &lt;span class=&quot;token number&quot;&gt;0.000000&lt;/span&gt;   &lt;span class=&quot;token number&quot;&gt;0.000000&lt;/span&gt;   &lt;span class=&quot;token number&quot;&gt;0.000000&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;  &lt;span class=&quot;token number&quot;&gt;0.000377&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
$ ruby lib/benchmark.rb
&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; Array Size: &lt;span class=&quot;token number&quot;&gt;1000&lt;/span&gt;
       user     system      total        real
   &lt;span class=&quot;token number&quot;&gt;0.120000&lt;/span&gt;   &lt;span class=&quot;token number&quot;&gt;0.010000&lt;/span&gt;   &lt;span class=&quot;token number&quot;&gt;0.130000&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;  &lt;span class=&quot;token number&quot;&gt;0.124929&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
   &lt;span class=&quot;token number&quot;&gt;0.010000&lt;/span&gt;   &lt;span class=&quot;token number&quot;&gt;0.000000&lt;/span&gt;   &lt;span class=&quot;token number&quot;&gt;0.010000&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;  &lt;span class=&quot;token number&quot;&gt;0.008825&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
$ ruby lib/benchmark.rb
&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; Array Size: &lt;span class=&quot;token number&quot;&gt;10000&lt;/span&gt;
       user     system      total        real
  &lt;span class=&quot;token number&quot;&gt;10.120000&lt;/span&gt;   &lt;span class=&quot;token number&quot;&gt;0.030000&lt;/span&gt;  &lt;span class=&quot;token number&quot;&gt;10.150000&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10.146124&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
   &lt;span class=&quot;token number&quot;&gt;0.520000&lt;/span&gt;   &lt;span class=&quot;token number&quot;&gt;0.000000&lt;/span&gt;   &lt;span class=&quot;token number&quot;&gt;0.520000&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;  &lt;span class=&quot;token number&quot;&gt;0.520377&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Comparing QuickFind (top line) with QuickUnion(bottom line), we can actually measure how well this small optimization of the union operation has increased performance with larger datasets.&lt;/p&gt;
&lt;p&gt;Awesome.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[State of the UnionFind]]></title><description><![CDATA[I was scraping the rust off my data-structures synapses last week, and found that there was still some functionality underneath. UnionFind…]]></description><link>http://katieleonard.ca/blog/2013/2013-07-30-state-of-the-unionfind/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2013/2013-07-30-state-of-the-unionfind/</guid><pubDate>Wed, 31 Jul 2013 05:29:03 GMT</pubDate><content:encoded>&lt;p&gt;I was scraping the rust off my data-structures synapses last week, and found that there was still some functionality underneath. UnionFind is one of those sneaky algorithms that crops up in non-linear arrangements of data, such as computer or social networks. Specifically, it keeps track of sets of connected elements. The API consists of a union(p, q), which connects the two elements p and q, and a find(p, q), which determines if p is in the same set as q.&lt;/p&gt;
&lt;p&gt;I learned about this algorithm through &lt;a href=&quot;https://www.coursera.org/&quot;&gt;Coursera&lt;/a&gt;, and their class &lt;a href=&quot;https://www.coursera.org/course/algs4partI&quot;&gt;Algorithms Part 1&lt;/a&gt; with Kevin Wayne and Robert Sedgewick. The focus of this course was not only on implementation of algorithms, but also optimization.&lt;/p&gt;
&lt;!--more--&gt;
&lt;h1&gt;Union Find&lt;/h1&gt;
&lt;p&gt;A simple model for connectivity is 10 objects numbered 1 through 0:&lt;/p&gt;
&lt;p&gt;0 1 2 3 4 5 6 7 8 9&lt;/p&gt;
&lt;p&gt;Making random connections will produce disjointed sets of objects:&lt;/p&gt;
&lt;p&gt;0 1 { 2 3 9 } { 5 6 } 7 { 4 8 }&lt;/p&gt;
&lt;p&gt;A find(p, q) will determine if p and q are in the same set:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;find(0, 8) =&gt; false&lt;/li&gt;
&lt;li&gt;find(2, 9) =&gt; true&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A union(p, q) will put p and q in the same set:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;union(1, 6) =&gt; 0 { 2 3 9 } { 1 5 6 } 7 { 4 8 }&lt;/li&gt;
&lt;li&gt;union(2, 4) =&gt; 0 1 { 5 6 } 7 { 2 3 9 4 8 }&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Using an array to keep track of the values, we can walk through what this implementation would look like:&lt;/p&gt;
&lt;table class=&quot;table table-bordered&quot;&gt;
  &lt;tr&gt;
    &lt;th&gt;Index&lt;/th&gt;
    &lt;td&gt;1&lt;/td&gt;
    &lt;td&gt;2&lt;/td&gt;
    &lt;td&gt;3&lt;/td&gt;
    &lt;td&gt;4&lt;/td&gt;
    &lt;td&gt;5&lt;/td&gt;
    &lt;td&gt;6&lt;/td&gt;
    &lt;td&gt;7&lt;/td&gt;
    &lt;td&gt;8&lt;/td&gt;
    &lt;td&gt;9&lt;/td&gt;
    &lt;td&gt;0&lt;/td&gt;
    &lt;th&gt;&lt;/th&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;th&gt;Value&lt;/th&gt;
    &lt;td&gt;1&lt;/td&gt;
    &lt;td&gt;2&lt;/td&gt;
    &lt;td&gt;3&lt;/td&gt;
    &lt;td&gt;4&lt;/td&gt;
    &lt;td&gt;5&lt;/td&gt;
    &lt;td&gt;6&lt;/td&gt;
    &lt;td&gt;7&lt;/td&gt;
    &lt;td&gt;8&lt;/td&gt;
    &lt;td&gt;9&lt;/td&gt;
    &lt;td&gt;0&lt;/td&gt;
    &lt;th&gt;&lt;/th&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;th&gt;union(4,9)&lt;/th&gt;
    &lt;td&gt;1&lt;/td&gt;
    &lt;td&gt;2&lt;/td&gt;
    &lt;td&gt;3&lt;/td&gt;
    &lt;td class=&quot;highlight&quot;&gt;9&lt;/td&gt;
    &lt;td&gt;5&lt;/td&gt;
    &lt;td&gt;6&lt;/td&gt;
    &lt;td&gt;7&lt;/td&gt;
    &lt;td&gt;8&lt;/td&gt;
    &lt;td class=&quot;highlight&quot;&gt;9&lt;/td&gt;
    &lt;td&gt;0&lt;/td&gt;
    &lt;td&gt; | Changes all values that match array[4] to match array[9]&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;th&gt;union(2,4)&lt;/th&gt;
    &lt;td&gt;1&lt;/td&gt;
    &lt;td class=&quot;highlight&quot;&gt;9&lt;/td&gt;
    &lt;td&gt;3&lt;/td&gt;
    &lt;td class=&quot;highlight&quot;&gt;9&lt;/td&gt;
    &lt;td&gt;5&lt;/td&gt;
    &lt;td&gt;6&lt;/td&gt;
    &lt;td&gt;7&lt;/td&gt;
    &lt;td&gt;8&lt;/td&gt;
    &lt;td class=&quot;highlight&quot;&gt;9&lt;/td&gt;
    &lt;td&gt;0&lt;/td&gt;
    &lt;td&gt; | Changes all values that match array[2] to match array[4]&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;th&gt;union(4,7)&lt;/th&gt;
    &lt;td&gt;1&lt;/td&gt;
    &lt;td class=&quot;highlight&quot;&gt;7&lt;/td&gt;
    &lt;td&gt;3&lt;/td&gt;
    &lt;td class=&quot;highlight&quot;&gt;7&lt;/td&gt;
    &lt;td&gt;5&lt;/td&gt;
    &lt;td&gt;6&lt;/td&gt;
    &lt;td class=&quot;highlight&quot;&gt;7&lt;/td&gt;
    &lt;td&gt;8&lt;/td&gt;
    &lt;td class=&quot;highlight&quot;&gt;7&lt;/td&gt;
    &lt;td&gt;0&lt;/td&gt;
    &lt;td&gt; | Changes all values that match array[4] to match array[7]&lt;/td&gt;
  &lt;/tr&gt;
&lt;/table&gt;
&lt;p&gt;Using the java api provided by Kevin Wayne and Robert Sedgewick:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;public class UF
----------------
public UF(int N)
public int find(int p, int q)
public void union(int p, int q)&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I adapted the basic union find in ruby:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;class QuickFind

  attr_accessor :find_array

  def initialize(size)
    @find_array = Array.new(size){ |index| index }
  end

  def find(p, q)
    location(p) == location(q)
  end

  def union(p, q)
    @find_array = create_union(p, q)
  end

  private

    def location(index)
      raise NotAnElement if @find_array[index].nil?
      return @find_array[index]
    end

    def create_union(p, q)
      target = location(p)
      goal = location(q)
      temp_array = @find_array.map do |element|
        element == target ? goal : element
      end
    end
end

class NotAnElement &amp;lt; Exception
end&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Sets are arranged as a flat array of elements which all share the same value: they are all wearing the same t-shirt. When we connect elements from different sets, we must make sure that every element in the first set changes its t-shirt to match the elements in the other set. This is a time-consuming process, and uses a lot of t-shirts.&lt;/p&gt;
&lt;p&gt;This implementation is called QuickFind because in an array of 1,000,000 entries, finding if two elements are connected is easy (compare the t-shirt at index p with the t-shirt at index q), but connecting them requires inspection of every element in the array in order (check everyone’s t-shirts) to make sure all the previous connections remain in place.&lt;/p&gt;
&lt;h2&gt;Benchmark&lt;/h2&gt;
&lt;p&gt;To compare efficiency of this and future UnionFind implementations, I built a basic benchmark that performs a set number of union and find operations and measures the time to completion:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;require &apos;benchmark&apos;
@size = 10000

def testUnit(object)
  @size.times do
    object.union(rand(@size), rand(@size))
    object.find(rand(@size), rand(@size))
  end
end

Benchmark.bm do |x|
  x.report { testUnit(QuickFind.new(@size)) }
end&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Running the benchmark on QuickFind:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ ruby lib/benchmark.rb
&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; Array size &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;100&lt;/span&gt;
       user     system      total        real
   &lt;span class=&quot;token number&quot;&gt;0.000000&lt;/span&gt;   &lt;span class=&quot;token number&quot;&gt;0.000000&lt;/span&gt;   &lt;span class=&quot;token number&quot;&gt;0.000000&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;  &lt;span class=&quot;token number&quot;&gt;0.002745&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
$ ruby lib/benchmark.rb
&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; Array size &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1000&lt;/span&gt;
       user     system      total        real
   &lt;span class=&quot;token number&quot;&gt;0.140000&lt;/span&gt;   &lt;span class=&quot;token number&quot;&gt;0.000000&lt;/span&gt;   &lt;span class=&quot;token number&quot;&gt;0.140000&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;  &lt;span class=&quot;token number&quot;&gt;0.137957&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
$ ruby lib/benchmark.rb
&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; Array size &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10000&lt;/span&gt;
       user     system      total        real
  &lt;span class=&quot;token number&quot;&gt;13.790000&lt;/span&gt;   &lt;span class=&quot;token number&quot;&gt;0.020000&lt;/span&gt;  &lt;span class=&quot;token number&quot;&gt;13.810000&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;13.866528&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;You can see from these measurements that increasing the size of the array by a factor of 10 each time comes with a logarithmic increase in processing time. There is definitely room for optimization, so stay tuned for more refinements. In the meantime,&lt;/p&gt;
&lt;h2&gt;Fun Rubyisms&lt;/h2&gt;
&lt;p&gt;Array initialization is a snap in ruby! Compare the initialization line in the QuickFind algorithm above with the equivalent java implementation:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;@find_array = Array.new(size){ |index| index }&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;versus&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;...
int[] arry = new int[size]
for (int i = 0; i &amp;lt; size; i++) {
    id[i] = i;
}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Both result in an array of the specified size, but ruby is slightly less sprawling.&lt;/p&gt;
&lt;p&gt;Also, check out lines 27 - 29&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;temp_array = @find_array.map do |element|
  element == target ? goal : element
end&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Using map() eliminates the need for a separate array declaration. It is the equivalent of:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;temp_array = []
@find_array.each do |element|
  temp_array &amp;lt;&amp;lt; element == target ? goal : element
end
return temp_array&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;and is certainly more readable than the equivalent in java:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;int pid = id[p];
for (int i = 0; i &amp;lt; id.length; i++)
    if (id[i] == pid) id[i] = id[q];&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Awesome&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Procuring Provisions]]></title><description><![CDATA[I was trying to add a database to my JSGames app — it is a basic sinatra app with a few goodies already in place — and I was having some…]]></description><link>http://katieleonard.ca/blog/2013/2013-07-27-procuring-provisions/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2013/2013-07-27-procuring-provisions/</guid><pubDate>Sun, 28 Jul 2013 05:29:03 GMT</pubDate><content:encoded>&lt;p&gt;I was trying to add a database to my JSGames app — it is a basic sinatra app with a few goodies already in place — and I was having some difficulty deploying it to Heroku. Rails (for the most part) automagically creates and maintains its database, and as long as I remember to move any references to sqlite3 into the development and test environments, I have never had trouble provisioning one on Heroku either. Rolling a web application from scratch with sinatra, however, requires a little more savvy.&lt;/p&gt;
&lt;!--more--&gt;
&lt;p&gt;My Gemfile had a familiar structure:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ruby&quot;&gt;&lt;pre class=&quot;language-ruby&quot;&gt;&lt;code class=&quot;language-ruby&quot;&gt;source &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&apos;https://rubygems.org&apos;&lt;/span&gt;&lt;/span&gt;
ruby &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&apos;2.0.0&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
gem &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;sinatra&quot;&lt;/span&gt;&lt;/span&gt;
gem &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;activerecord&quot;&lt;/span&gt;&lt;/span&gt;
gem &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;sinatra-activerecord&quot;&lt;/span&gt;&lt;/span&gt;
gem &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;pg&quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;So far, so familiar. I added config/environments.rb to outline the details of the database I would like provisioned (using postgres locally as well as in production):&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ruby&quot;&gt;&lt;pre class=&quot;language-ruby&quot;&gt;&lt;code class=&quot;language-ruby&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&apos;active_record&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&apos;uri&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
db &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;URI&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;parse&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;ENV&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&apos;DATABASE_URL&apos;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&apos;postgres://localhost/mydb&apos;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
ActiveRecord&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;Base&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;establish_connection&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;token symbol&quot;&gt;:adapter&lt;/span&gt;  &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; db&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;scheme &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&apos;postgres&apos;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&apos;postgresql&apos;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; db&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;scheme&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token symbol&quot;&gt;:host&lt;/span&gt;     &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; db&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;host&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token symbol&quot;&gt;:port&lt;/span&gt;     &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; db&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;port&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token symbol&quot;&gt;:username&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; db&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token symbol&quot;&gt;:password&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; db&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;password&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token symbol&quot;&gt;:database&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; db&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;path&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token symbol&quot;&gt;:encoding&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&apos;utf8&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;With everything complete, I created a couple of models, migrated, tested it locally, and committed the changes. Heroku compiles the slug just fine, but when I open the application I get the too familiar “Application Error” page. The logs tell me: &lt;pre&gt;ERROR: Invalid DATABASE_URL&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Huh? My url is the one that Heroku suggested! How can it be invalid? It was working fine locally, what is the problem? Here is a sample of my google searches from that frantic afternoon:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ERROR: Invalid DATABASE_URL heroku&lt;/li&gt;
&lt;li&gt;deploying sinatra pg heroku&lt;/li&gt;
&lt;li&gt;environment variables&lt;/li&gt;
&lt;li&gt;heroku config variables&lt;/li&gt;
&lt;li&gt;usr-env-compile heroku&lt;/li&gt;
&lt;li&gt;heroku can’t connect to server&lt;/li&gt;
&lt;li&gt;how to roll back a push to heroku&lt;/li&gt;
&lt;li&gt;how to recover from the embarrassment of an offline portfolio project&lt;/li&gt;
&lt;li&gt;how to start a llama farm&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I finally found the answer (aka read the manual) with &lt;a href=&quot;https://devcenter.heroku.com/articles/heroku-postgresql&quot;&gt;Heroku Postgres&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;First: Check to see if your database has been provisioned&lt;/h3&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ heroku addons &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;grep&lt;/span&gt; POSTGRES&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I ran this command in my sinatra project and found nothing. NOTHING!&lt;/p&gt;
&lt;p&gt;When Heroku told me that it couldn’t find my database, that is because it hadn’t MADE my database. So I…&lt;/p&gt;
&lt;h3&gt;Second: Create a new database&lt;/h3&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ heroku addons:add heroku-postgresql:dev
Adding heroku-postgresql:dev on js-games&lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;. done, v42 &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;free&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
Attached as HEROKU_POSTGRESQL_GOLD_URL
Database has been created and is available
 &lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt; This database is empty. If upgrading, you can transfer
 &lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt; data from another database with pgbackups:restore.
Use &lt;span class=&quot;token variable&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;`&lt;/span&gt;heroku addons:docs heroku-postgresql:dev&lt;span class=&quot;token variable&quot;&gt;`&lt;/span&gt;&lt;/span&gt; to view documentation.&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;YAY! My database has been created and found. Still, nothing wrong with…&lt;/p&gt;
&lt;h3&gt;Third: Double check your database exists&lt;/h3&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ heroku config
&lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; js-games Config Vars
HEROKU_POSTGRESQL_GOLD_URL: postgres://&lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;.@ec2-&lt;span class=&quot;token comment&quot;&gt;##-###-###-##.compute-1.amazonaws.com:####&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Heroku confesses that my database is stored on AWS, and gives a fairly detailed address (redacted on the grounds of national security).&lt;/p&gt;
&lt;h3&gt;Fourth: Promote the new database to primary&lt;/h3&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ heroku pg:promote HEROKU_POSTGRESQL_GOLD_URL
Promoting HEROKU_POSTGRESQL_GOLD_URL to DATABASE_URL&lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;. &lt;span class=&quot;token keyword&quot;&gt;done&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;Fifth: Check out the new database&lt;/h3&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ heroku pg:info
&lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; HEROKU_POSTGRESQL_GOLD_URL &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;DATABASE_URL&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
Plan:        Dev
Status:      available
Connections: &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;
PG Version:  &lt;span class=&quot;token number&quot;&gt;9.2&lt;/span&gt;.4
Created:     &lt;span class=&quot;token number&quot;&gt;2013&lt;/span&gt;-07-27 &lt;span class=&quot;token number&quot;&gt;22&lt;/span&gt;:46 UTC
Data Size:   &lt;span class=&quot;token number&quot;&gt;6.3&lt;/span&gt; MB
Tables:      &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;
Rows:        &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/10000 &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;In compliance&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
Fork/Follow: Unsupported&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;TADA&lt;/h3&gt;
&lt;p&gt;Do one final push to heroku and restart the server:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; commit -a -m &lt;span class=&quot;token string&quot;&gt;&quot;fixes the last two hours of disasterous troubleshooting&quot;&lt;/span&gt;
$ &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; push heroku master
&lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;.
$ heroku restart&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Awesome&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Git-Picking]]></title><description><![CDATA[or, How to mine for cherries with Git When I work on an experimental feature in a project branch, I have often found that I will have a…]]></description><link>http://katieleonard.ca/blog/2013/2013-07-24-git-picking/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2013/2013-07-24-git-picking/</guid><pubDate>Thu, 25 Jul 2013 05:29:03 GMT</pubDate><content:encoded>&lt;h4&gt;or, How to mine for cherries with Git&lt;/h4&gt;
&lt;p&gt;When I work on an experimental feature in a project branch, I have often found that I will have a mixture of commits I would like to keep, and commits that I wish had never happened.
Using the principle of only committing atomic changes, and enjoying the fruits of your detailed-commit-message labour, there is a way to extract the gold from the ore, so to speak.&lt;/p&gt;
&lt;!--more--&gt;
&lt;h2&gt;Locate the gold&lt;/h2&gt;
&lt;p&gt;Checkout the branch that contains your experiment, and use git log to get a list of all the commits:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; checkout form_feature_branch
$ &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; log --pretty&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;oneline
a83f4c3aa5d800f846d075748a79a326e0971f67 reorg gemfile
197964c091905a76f2172ca11fcbd49ccfb83c67 adds blog.db
a793fe00c50a5956c5e9f7be48ac5a9861b1eb95 adds forme form to edit&lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;.
8394b37494b63754f42ecaf19244fe6d8a36942f adds gitignore &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; db &lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;.
c52a6fd3f1706584ce3e47abf49ed627a1e28fd3 adds bundler gem &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; manag&lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;.
1686664c4a98221ea04377bcbcf946e62a9f1cfa removes gems &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; simple&lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;.
034d309a612dcce6f10bb55f0da2e78b2f7c10b1 adds cells to project
&lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;.&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In form&lt;em&gt;feature&lt;/em&gt;branch I was testing out different implementations of form generation in erb views. I tried a couple of different gems and found one that suits my sinatra project: &lt;a href=&quot;https://github.com/jeremyevans/forme&quot;&gt;Forme&lt;/a&gt; is easy to use with or without models, and has great sinatra integration and documentation. Also along the way, I discovered how to include bundler for managing file dependencies and did some minor refactoring of my Gemfile.&lt;/p&gt;
&lt;p&gt;I wanted to keep the gem reorganization, as well as the forme, bundler, and gitignore commits, so I made this list of keeper-commits:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;a83f4c3aa5d800f846d075748a79a326e0971f67 reorg gemfile
a793fe00c50a5956c5e9f7be48ac5a9861b1eb95 adds forme form to edit&lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;.
c52a6fd3f1706584ce3e47abf49ed627a1e28fd3 adds bundler gem &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; manag&lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;.
8394b37494b63754f42ecaf19244fe6d8a36942f adds gitignore &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; db &lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;.&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Everything else is cruft.&lt;/p&gt;
&lt;h2&gt;Extract the gold&lt;/h2&gt;
&lt;p&gt;With this list of golden commits in hand, checkout a fresh branch and cherry-pick the commits you like!&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; checkout -b form_feature_additions
$ &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; cherry-pick &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;commit_identifier&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Do this command for each good commit:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; cherry-pick a83f4c3aa5d800f846d075748a79a326e0971f67
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;master form_feature_additions&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; reorg gemfile
 &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;file&lt;/span&gt; changed, &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt; insertions&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;+&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;, &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt; deletions&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;-&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
 changed mode &lt;span class=&quot;token number&quot;&gt;100644&lt;/span&gt; Gemfile
$ &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; cherry-pick a793fe00c50a5956c5e9f7be48ac5a9861b1eb95
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;master form_feature_additions&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; adds forme form to edit&lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;.
&lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;.
$ &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; cherry-pick c52a6fd3f1706584ce3e47abf49ed627a1e28fd3
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;master form_feature_additions&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; adds bundler gem &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; manag&lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;.
$ &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; cherry-pick 8394b37494b63754f42ecaf19244fe6d8a36942f
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;master form_feature_additions&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; adds gitignore &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; db &lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;.
&lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;.&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;If you look at your git status you will see&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# On branch form_feature_additions&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# Your branch is ahead of &apos;origin/master&apos; by 4 commits.&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Profit&lt;/h2&gt;
&lt;p&gt;Now you can merge this branch with master, or continue fleshing out the feature on a clean branch, keeping only the good stuff and abandoning the bad, making experimentation easy.&lt;/p&gt;
&lt;p&gt;AWESOME&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Sinatra in a console]]></title><description><![CDATA[Sinatra does not have a default console like rails does. If you are writing in a rails environment and need to test out a helper method, or…]]></description><link>http://katieleonard.ca/blog/2013/2013-07-22-sinatra-in-a-console/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2013/2013-07-22-sinatra-in-a-console/</guid><pubDate>Mon, 22 Jul 2013 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Sinatra does not have a default console like rails does. If you are writing in a rails environment and need to test out a helper method, or want to check on the state of a record in the database, dropping down into the rails console is as easy as typing:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ rails c&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;How can we achieve the same ability in Sinatra?&lt;!--more--&gt;&lt;/p&gt;
&lt;h3&gt;Tux&lt;/h3&gt;
&lt;p&gt;Tux is a ruby gem that generates a sinatra console. It reads the config.ru, allows you to interact with App methods, and provides empty request and response objects to for investigating communication between views and the Sinatra controller.&lt;/p&gt;
&lt;p&gt;Add Tux to your Gemfile:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;group :development, :test do
  ...
  gem &apos;tux&apos;
end&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Don’t forget to bundle!&lt;/p&gt;
&lt;p&gt;At the command line, start up tux and use rack.actions to view all the methods available:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ tux
Loading development environment &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Rack &lt;span class=&quot;token number&quot;&gt;1.2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt; rack.actions
&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;:request, :get, :post, :put, :patch, :delete, :options, :head, :follow_redirect&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;, :header, :set_cookie, :clear_cookies, :authorize, :basic_authorize, :digest_authorize, :last_response, :last_request&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;You can access any method from your application as well.
Of course, if you are working in Sinatra, you probably want to go as lightweight as possible, which is why you can also use:&lt;/p&gt;
&lt;h3&gt;Basic irb&lt;/h3&gt;
&lt;p&gt;It is as simple as using irb and requiring your main app file. You have access to all the dependencies and files that your application does by simply requiring that one file. You can check state, call methods, create objects, whatever you need:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ irb
&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; require &lt;span class=&quot;token string&quot;&gt;&apos;./app.rb&apos;&lt;/span&gt;
 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; User.all
D, &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2013&lt;/span&gt;-07-22T15:47:49.230146 &lt;span class=&quot;token comment&quot;&gt;#54081] DEBUG -- :   User Load (0.2ms)  SELECT &quot;users&quot;.* FROM &quot;users&quot;&lt;/span&gt;
 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;#&amp;lt;ActiveRecord::Relation [#&amp;lt;User id: 1, name: &quot;Gordon Shumway&quot;, email: &quot;gordon@example.com&quot;, created_at: &quot;2013-07-22 22:45:48&quot;, updated_at: &quot;2013-07-22 22:45:48&quot;&gt;, #&amp;lt;User id: 2, name: &quot;Fanny Eubanks&quot;, email: &quot;fanny@example.com&quot;, created_at: &quot;2013-07-22 22:45:48&quot;, updated_at: &quot;2013-07-22 22:45:48&quot;&gt;]&gt;&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This can be called even more elegantly at the command line:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ irb -r ./app.rb&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;or through a Rake task:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;desc &lt;span class=&quot;token string&quot;&gt;&quot;run irb console&quot;&lt;/span&gt;
task :console, :environment &lt;span class=&quot;token keyword&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt;t, args&lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt;
  ENV&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;RACK_ENV&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; args&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;:environment&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;development&apos;&lt;/span&gt;
  &lt;span class=&quot;token builtin class-name&quot;&gt;exec&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;irb -r irb/completion -r ./app.rb&quot;&lt;/span&gt;
end&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Awesome&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Get your kicks on route localhost:4567]]></title><description><![CDATA[I am building a code breaking game along the lines of Mastermind and I encountered a block. The problem I have a javascript that generates a…]]></description><link>http://katieleonard.ca/blog/2013/2013-07-17-get-your-kicks-on-localhost4567/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2013/2013-07-17-get-your-kicks-on-localhost4567/</guid><pubDate>Wed, 17 Jul 2013 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I am building a code breaking game along the lines of Mastermind and I encountered a block.&lt;/p&gt;
&lt;h2&gt;The problem&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;I have a javascript that generates a secret code.&lt;/li&gt;
&lt;li&gt;I have a ruby class that compares a guess to the secret code and returns an analysis of the accuracy of the guess.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;How do I get the ruby class to process a guess and secret code from the browser?&lt;/p&gt;
&lt;!--more--&gt;
&lt;h2&gt;I learned something about Ajax today.&lt;/h2&gt;
&lt;p&gt;An ajax call is built up from a few minimum parameters: a url, the HTTP method, the dataType expected, and a callback function that handles the return. You can include data from the user in the form of a data hash:&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; the_url &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;http://&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; window&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;location&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;host &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;/game/&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; guess_string&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; mark_string &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; $&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;ajax&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;POST&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; the_url&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;accepts&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;application/json&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;dataType&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;json&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token string-property property&quot;&gt;&apos;code&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; secret_code &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token function-variable function&quot;&gt;complete&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      output_mark &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; data&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;responseText&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token function&quot;&gt;process_output&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;secret_code&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; guess_string&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; output_mark&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This code snippet is using Ajax to send the secret code and guess to the Sinatra route.&lt;/p&gt;
&lt;h2&gt;I learned something about Sinatra today.&lt;/h2&gt;
&lt;p&gt;A route has three ingredients: an HTTP method, a URL matching pattern, and a code block.
Typically they look like this:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;get &apos;/&apos; do
  &quot;hello world&quot;
end&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;But they can also look like this:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;post &apos;/game/:guess&apos; do
  game.guess(params[:guess])
end
private
  def game
    @game ||= Mastermind::Game.new_with_code(params[:code])
  end&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The code block returns information. That information can be anything, from a plain string (first example), or an html web page, to a JSON representation of an object (second example). What the browser does with the information it receives is the browser’s business.&lt;/p&gt;
&lt;p&gt;The overall workflow:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The url on my local machine looks like this: ”&lt;a href=&quot;http://localhost:4567/game/12345&quot;&gt;http://localhost:4567/game/12345&lt;/a&gt;” (line 1). The submitted guess is 12345.&lt;/li&gt;
&lt;li&gt;Ajax packages the url with the data hash containing the secret code (line 7).&lt;/li&gt;
&lt;li&gt;Javascript submits the HTTP POST request to Sinatra which matches the route.&lt;/li&gt;
&lt;li&gt;The route creates a Mastermind::Game object with the provided secret code.&lt;/li&gt;
&lt;li&gt;The route calls the guess method on the Game object with the submitted guess.&lt;/li&gt;
&lt;li&gt;The route returns a json of the method output (in this case it is a string of +/- characters indicating exact number matches(+) or matched numbers in the wrong position(-)).&lt;/li&gt;
&lt;li&gt;In the ajax callback function the data from the json object is parsed and passed on for further processing.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;I learned something about routes today.&lt;/h2&gt;
&lt;p&gt;I had a mental block about routes. I thought that building the “/game/:guess” route in Sinatra meant that the user would be constantly navigating between “/mastermind” and “/game/:guess”, and that the game would always be reloading with a new secret. I was thinking about routes the wrong way — when javascript calls the route, it doesn’t reload the page, it just retrieves data! I had conflated routes with navigation in my imagination, and forgot that a route is just a method call containing a request for information. Just because the information returned is often rendered as an html page doesn’t mean that it has to be html. Which leads me to the penultimate point…&lt;/p&gt;
&lt;h2&gt;I learned something about curl today.&lt;/h2&gt;
&lt;p&gt;ANYTHING can make an HTTP request. Ok, maybe that is a slight overstatement.&lt;/p&gt;
&lt;p&gt;Browsers interpret the information retrieved using HTTP requests, but they are far from the only category of software that can. Turns out, the command-line functions just as well:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ &lt;span class=&quot;token function&quot;&gt;curl&lt;/span&gt; -X POST -H &lt;span class=&quot;token string&quot;&gt;&quot;Accept: application/json&quot;&lt;/span&gt; -d &lt;span class=&quot;token string&quot;&gt;&quot;code=12345&quot;&lt;/span&gt; js-games.herokuapp.com/12345
+++++$&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The command on line 1 will return the same string I am retrieving with $.ajax in javascript (output on line2). Sure it is a fairly plain result — it doesn’t even include a new line character, for pity’s sake — but it does the job of making an HTTP request to a route and using the result.&lt;/p&gt;
&lt;h2&gt;I learned something about myself today.&lt;/h2&gt;
&lt;p&gt;I didn’t even realize I was misunderstanding HTTP! It was one of those concepts I had already checked off my mental list of technologies to cover on my quest to become a web developer. This breakthrough has reminded me that reviewing the fundamentals in the context of learning new technologies will bring a deeper understanding of everything.&lt;/p&gt;
&lt;p&gt;Awesome&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Mass assignment X Gravity]]></title><description><![CDATA[What is Mass Assignment? Mass assignment is using a ruby-esque shortcut to interact with models: This is NOT mass assignment. Each param is…]]></description><link>http://katieleonard.ca/blog/2013/2013-07-15-mass-assignment-x-gravity/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2013/2013-07-15-mass-assignment-x-gravity/</guid><pubDate>Mon, 15 Jul 2013 00:00:00 GMT</pubDate><content:encoded>&lt;h3&gt;What is Mass Assignment?&lt;/h3&gt;
&lt;p&gt;Mass assignment is using a ruby-esque shortcut to interact with models&lt;!--more--&gt;:&lt;/p&gt;
&lt;p&gt;This is NOT mass assignment.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;def create
  u = User.new
  u.first_name = params[:user][:firstname]
  u.last_name = params[:user][:lastname]
  if u.save
    redirect_to :index, flash: { success: &quot;Created!&quot; }
  else
    render :action =&gt; &apos;new&apos;
  end
end&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Each param is extracted from the params hash and assigned explicitly. Any params that are not assigned are thrown on the floor.&lt;/p&gt;
&lt;p&gt;This IS mass assignment.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;def create
  u = User.new(params[:user])
  if u.save
    redirect_to :index, flash: { success: &quot;Created!&quot; }
  else
    render :action =&gt; &apos;new&apos;
  end
end&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The programmer assumes that the params include all the data necessary, and &lt;em&gt;only&lt;/em&gt; the data necessary. All params in the hash are used to create the new user record.&lt;/p&gt;
&lt;h3&gt;Why is mass assignment a problem?&lt;/h3&gt;
&lt;p&gt;The problem with mass assignment is that if you have a sensitive tag in your model, for example user&lt;em&gt;type (which could be set to admin), a malicious user can add `user[:user&lt;/em&gt;type] = ‘admin’` to your params hash. Your controller will unwittingly include it in the save command, creating a new admin account for the  malicious user.&lt;/p&gt;
&lt;h3&gt;Is there any way to prevent this diabolical schema scheme?&lt;/h3&gt;
&lt;p&gt;There is! With Rails 4 comes &lt;strong&gt;strong params&lt;/strong&gt;.
Strong params live in the controller and tell it explicitly what params can be trusted.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;def create
  u = User.new(user_params)
  if u.save
    redirect_to :index, flash: { success: &quot;Created!&quot; }
  else
    render :action =&gt; &apos;new&apos;
  end
end
...
def user_params
  params.require(:user).permit(:name, :email, :password, :password_confirmation)
end&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The only parameters our controller will send to the model are those specified on our white-list. If rails detects a user attempting to access a param that is not on the white-list, said user had better be prepared for &lt;em&gt;grave consequences&lt;/em&gt;. Their session will be &lt;strong&gt;deleted&lt;/strong&gt;, their attempt will be &lt;strong&gt;logged&lt;/strong&gt;, and Rails will email their mother.&lt;/p&gt;
&lt;p&gt;Awesome.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Best Practices - Pull Requests]]></title><description><![CDATA[Learning how to contribute to open source projects has been really exciting. Adding value to existing projects, getting social in the coding…]]></description><link>http://katieleonard.ca/blog/2013/2013-07-11-best-practices-pull-requests/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2013/2013-07-11-best-practices-pull-requests/</guid><pubDate>Thu, 11 Jul 2013 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Learning how to contribute to open source projects has been really exciting. Adding value to existing projects, getting social in the coding community, and working on production-level code has been a steep but rewarding learning curve. One important thing to learn is the etiquette of creating pull requests. I read a great post about what to include in a &lt;a href=&quot;http://dev.solita.fi/2013/07/04/whats-in-a-good-commit.html&quot;&gt;good commit&lt;/a&gt;, but I also needed to know how to make a good pull request&lt;!--more--&gt;:&lt;/p&gt;
&lt;h3&gt;Branch it&lt;/h3&gt;
&lt;p&gt;Before making any changes to an open source project, open a new branch. This will allow you to isolate your changes into separate pull requests. For example, I add Feature A, push to master, and create pull request 1. The next day, I add Feature B, push to master, and create pull request 2. If Feature A has not already been reviewed and accepted, Feature B additions will now be encorporated into pull request 1. This is bad practice. Keep each contribution in a separate branch. This will also allow you to keep your current branch up to date with the upstream repository, without affecting your previous work.&lt;/p&gt;
&lt;h3&gt;One change, one commit&lt;/h3&gt;
&lt;p&gt;A commit is not just a backup. Like a migration, your commit history should read like a road map of changes you make to get to your current state — and changes you should undo when things go wrong. If your commits change dozens of lines of code, understanding the changes is going to require a deep dive into the code.&lt;/p&gt;
&lt;h3&gt;Pithy commit messages&lt;/h3&gt;
&lt;p&gt;Make it easy on your code reviewer by making your commits small enough, and your commit messages detailed enough that they can be understood at a glance.&lt;/p&gt;
&lt;p&gt;The workflow, in general:&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;fork the repo&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;git clone&lt;/code&gt; to local machine&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;git checkout -b featureA&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;git pull upstream master&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;make your changes&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;git commit -am &quot;adds one addition to feature A&quot;&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;git push origin featureA&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;make pull request&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Awesome&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Partial to Sinatra]]></title><description><![CDATA[Having just discovered the magic of using partials to refactor html in rails, imagine my delight when I found it to be even easier in…]]></description><link>http://katieleonard.ca/blog/2013/2013-07-09-partial-to-sinatra/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2013/2013-07-09-partial-to-sinatra/</guid><pubDate>Tue, 09 Jul 2013 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Having just discovered the magic of using partials to refactor html in rails, imagine my delight when I found it to be even easier in Sinatra.&lt;/p&gt;
&lt;!--more--&gt;
&lt;p&gt;A partial is a just a fragment of html (or erb). They can be used for rendering duplicate or dynamic content into otherwise static pages.&lt;/p&gt;
&lt;p&gt;I was writing html for my JSGames sinatra application when I caught myself copying a snippet of html onto my clipboard. Why on earth would I duplicate code? I want to include a block of text on both the index and the game page, but I don’t want to have to modify it in two places when I inevitably get around to rewriting it.&lt;/p&gt;
&lt;p&gt;The solution?&lt;/p&gt;
&lt;p&gt;Factor out the duplicate html into a partial (begin name with _ for identification purposes). For example &lt;code class=&quot;language-text&quot;&gt;_gameDescription.erb&lt;/code&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;html&quot;&gt;&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;h1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Game Title&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;h1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Game description&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Add that partial wherever you want to display this snippet of code:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;&amp;lt;%= erb :_gameDescription  %&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;For example:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;&amp;lt;div class=&quot;span4 pagination-centered&quot;&gt;
  &amp;lt;%= erb :_solitaireDesc  %&gt;
  &amp;lt;a href=&quot;/game&quot; class=&quot;btn btn-large&quot;&gt;Play&amp;lt;/a&gt;
&amp;lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Check out the final product on &lt;a href=&quot;http://js-games.herokuapp.com/solitaire&quot;&gt;JSGames&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Awesome&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Red, Green, Refactor! A Workflow for Rails]]></title><description><![CDATA[1. Write a failing test Use the failures to drive development: 2. No Route Add one to /config/routes.rb: 3.No Controller Add one to…]]></description><link>http://katieleonard.ca/blog/2013/2013-07-03-red-green-refactor/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2013/2013-07-03-red-green-refactor/</guid><pubDate>Wed, 03 Jul 2013 00:00:00 GMT</pubDate><content:encoded>&lt;h3&gt;1. Write a failing test&lt;/h3&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;describe &quot;Static About page&quot; do
  it &quot;should have the content &apos;About Us&apos;&quot; do
    visit &apos;/static_pages/about&apos;
    page.should have_content(&apos;About Us&apos;)
  end
end&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Use the failures to drive development&lt;!--more--&gt;:&lt;/p&gt;
&lt;h3&gt;2. No Route&lt;/h3&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;Failures:
  &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; Static About page should have the content &lt;span class=&quot;token string&quot;&gt;&apos;About Us&apos;&lt;/span&gt;
     Failure/Error: visit &lt;span class=&quot;token string&quot;&gt;&apos;/static_pages/about&apos;&lt;/span&gt;
     ActionController::RoutingError:
       No route matches &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;GET&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;/static_pages/about&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Add one to /config/routes.rb:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;DemoApp2::Application.routes.draw do
  get &quot;static_pages/about&quot;
  ...
end&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;3.No Controller&lt;/h3&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;Failures:

  &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; Static About page should have the content &lt;span class=&quot;token string&quot;&gt;&apos;About Us&apos;&lt;/span&gt;
     Failure/Error: visit &lt;span class=&quot;token string&quot;&gt;&apos;/static_pages/about&apos;&lt;/span&gt;
     AbstractController::ActionNotFound:
       The action &lt;span class=&quot;token string&quot;&gt;&apos;about&apos;&lt;/span&gt; could not be found &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; StaticPagesController&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Add one to /controllers/static&lt;em&gt;pages&lt;/em&gt;controller.rb&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;class StaticPagesController &amp;lt; ApplicationController
  def about
  end
end&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;4. No Page&lt;/h3&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;Failures:
  1) Static About page should have the content &apos;About Us&apos;
     Failure/Error: visit &apos;/static_pages/about&apos;
     ActionView::MissingTemplate:
       Missing template static_pages/about, application/about with {:locale=&gt;[:en], :formats=&gt;[:html], :handlers=&gt;[:erb, :builder, :raw, :ruby, :jbuilder, :coffee]}.&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Add a view to /static_pages/about.html.erb&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;html&quot;&gt;&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token doctype&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;!&lt;/span&gt;&lt;span class=&quot;token doctype-tag&quot;&gt;DOCTYPE&lt;/span&gt; &lt;span class=&quot;token name&quot;&gt;html&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;body&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;h1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;About Us&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;h1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;body&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;html&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</content:encoded></item><item><title><![CDATA[No index.html, no cry]]></title><description><![CDATA[Following along with Rails tutorial by Michael Hartl, I built a sample app with a simple database, linking users to microposts in a twitter…]]></description><link>http://katieleonard.ca/blog/2013/2013-06-29-no-indexhtml-no-cry/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2013/2013-06-29-no-indexhtml-no-cry/</guid><pubDate>Sat, 29 Jun 2013 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Following along with &lt;a href=&quot;http://www.amazon.com/Ruby-Rails-Tutorial-Addison-Wesley-Professional/dp/0321832051&quot;&gt;Rails tutorial&lt;/a&gt; by Michael Hartl, I built a sample app with a simple database, linking users to microposts in a twitter-like manner. Everything worked well locally, but when it came time to deploy on heroku, I ran across some interesting stumbling blocks&lt;!--more--&gt;:&lt;/p&gt;
&lt;h3&gt;Rails 4 does not come with a default index.html&lt;/h3&gt;
&lt;p&gt;There I was, gleefully watching the slug compile on heroku (after several abortive attempts I realized I had not moved the sqlite3 gem into the development environment — heroku doesn’t like that). All seemed fine, I typed&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ heroku open&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;and what greeted me? A 404 error page! Something has gone horribly wrong! I have been rejected by heroku! I try again from the beginning, ensuring I have followed all the steps.. what could I have missed? Same result. But, Mr. Hartl, said it was easy… what was I missing?&lt;/p&gt;
&lt;p&gt;After some digging, I found a &lt;a href=&quot;https://devcenter.heroku.com/articles/rails4-getting-started&quot;&gt;heroku tutorial&lt;/a&gt; on getting started with the shiny new Rails 4. Deep inside this article, I found the magic words:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“Note: that Rails 4 no longer has a static index page in production, if you’re using a new app, there may be no root page.”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Orly? Are you saying that the 404 error I was getting was actually generated by my properly deployed app? YES! I made some obvious change to the html&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;html&quot;&gt;&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;title&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;You made it!&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;title&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;and redeployed. TADA!&lt;/p&gt;
&lt;p&gt;Awesome.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Hoisting with JavaScript]]></title><description><![CDATA[I am really enjoying Test-Driven Development by Christian Johansen I picked up this little gem this morning as I was learning about…]]></description><link>http://katieleonard.ca/blog/2013/2013-06-26-hoisting-with-javascript/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2013/2013-06-26-hoisting-with-javascript/</guid><pubDate>Wed, 26 Jun 2013 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I am really enjoying &lt;a href=&quot;http://www.amazon.com/Test-Driven-JavaScript-Development-Developers-Library/dp/0321683919&quot;&gt;Test-Driven Development&lt;/a&gt; by Christian Johansen&lt;/p&gt;
&lt;p&gt;I picked up this little gem this morning as I was learning about functions and the various objects associated with them:&lt;/p&gt;
&lt;p&gt;You CANNOT use function declarations in conditionals. &lt;!--more--&gt;Take this example:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;if (String.prototype.trim) {
  function trim(str) {
    return str.trim();
  }
else {
  function trim(str){
    return str.replace(/^\s+|\s+$/g, &quot;&quot;);
  }
}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;What is wrong with that, you might ask? HOISTING! Both functions are hoisted up to the global variable before execution, which means that the second one always overwrites the first one.&lt;/p&gt;
&lt;p&gt;This is a better method:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;if(!String.prototype.trim) {
  String.prototype.trim = function trim() {
    return this.replace(/^\s+|\s+$/g, &quot;&quot;)
  }
}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This way, we are not overwriting any browser-available Trim methods, we are declaring the method on the String.prototype, which means it is available to ALL strings in scope, AND we have named it so that it will be more visible in a stack trace in case something goes wrong.&lt;/p&gt;
&lt;p&gt;AWESOME&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Javascript has spies]]></title><description><![CDATA[Spies vs Mocks vs Stubs? We are covering testing frameworks at PCS this week,
 particularly Jasmine and Sinon. Jasmine has a similar…]]></description><link>http://katieleonard.ca/blog/2013/2013-06-25-javascript-has-spies/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2013/2013-06-25-javascript-has-spies/</guid><pubDate>Tue, 25 Jun 2013 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;Spies vs Mocks vs Stubs?&lt;/h2&gt;
&lt;p&gt;We are covering testing frameworks at PCS this week,
particularly Jasmine and Sinon.&lt;/p&gt;
&lt;p&gt;Jasmine has a similar structure to RSpec:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;describe(&quot;Class to describe&quot;, function() {
  it(&quot;should have some behavior&quot;. function() {
    //assertions
  });
});&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Also similar to RSpec, Jasmine allows you to spy on behavior.&lt;!--more--&gt;
Using spies, I can watch a method call and collect information about it.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Want to know if it was called?&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;expect(method).toHaveBeenCalled()&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Want to know how many times?&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;expect(method.callCount).toEqual(3)&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Want to know how it was called?&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;expect(method).toHaveBeenCalledWith(args)&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For example:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;describe( &quot;Spy on methods&quot;, function () {
  it( &quot;should watch calls to console&quot;, function () {
    var mySpy = spyOn(console, &quot;log&quot;);
    console.log(&quot;test1&quot;);
    console.log(&quot;test2&quot;);
    console.log(&quot;test3&quot;);

    expect(mySpy.callCount).toEqual(3);
  });
});&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Tomorrow, I conquer Stubs and Mocks!&lt;/p&gt;</content:encoded></item><item><title><![CDATA[jQuery objects vs strings]]></title><description><![CDATA[Object blocker!! My pair was stuck for the longest time on the following code snip:  We expected out output to include three elements — the…]]></description><link>http://katieleonard.ca/blog/2013/2013-06-19-jquery-objects-vs-strings/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2013/2013-06-19-jquery-objects-vs-strings/</guid><pubDate>Wed, 19 Jun 2013 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;Object blocker!!&lt;/h2&gt;
&lt;p&gt;My pair was stuck for the longest time on the following code snip:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token function&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; new_square &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;$(&amp;lt;div class=&quot;square&quot;&gt;&amp;lt;/div&gt;)&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;body&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;on&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;click&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;.square&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// var my_square = $(this);&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toggleClass&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;blue&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    b &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;new_square&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;insertAfter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    a &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;new_square&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;insertBefore&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    b&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toggleClass&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;blue&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    a&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toggleClass&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;blue&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;!--more--&gt;
&lt;p&gt; We expected out output to include three elements — the original square, one
inserted after, and one inserted before. The output we were seeing included
only two squares: the original one and the square inserted before. If
we inverted the insert calls, we would see only one inserted after. We
were totally stumped until we printed out the content of new_square:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token function&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;&amp;lt;div class=&quot;square&quot;&gt;&amp;lt;/div&gt;&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt; We were actually passing a reference to a jQuery OBJECT into the insert methods,
so in essence, we were creating the object once and then passing it around to
different locations. When we changed new_square from a jQuery object:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; new_square &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;$(&amp;lt;div class=&quot;square&quot;&gt;&amp;lt;/div&gt;)&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt; to a string&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; new_square &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;&amp;lt;div class=&quot;square&quot;&gt;&amp;lt;/div&gt;&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt; We saw our third element appear no problem.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Namespaces and jQuery]]></title><description><![CDATA[Namespaces in jQuery getting you down? Chuck taught me a great trick today — how to avoid namespace
conflicts in jQuery: This function is…]]></description><link>http://katieleonard.ca/blog/2013/2013-06-18-solving-namespace-conflicts-with-jquery/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2013/2013-06-18-solving-namespace-conflicts-with-jquery/</guid><pubDate>Tue, 18 Jun 2013 00:00:00 GMT</pubDate><content:encoded>&lt;h3&gt;Namespaces in jQuery getting you down?&lt;/h3&gt;
&lt;p&gt;Chuck taught me a great trick today — how to avoid namespace
conflicts in jQuery&lt;!--more--&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;(function($){
...
})(jQuery);&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This function is being passed jQuery as an argument, and is
assigning it the local variable $ — allowing you to use
the $ and reference the jQuery library.&lt;/p&gt;
&lt;p&gt;Awesome.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Blogging with Jekyll Bootstrap]]></title><description><![CDATA[Building a portfolio has been a lot of fun and has required a couple of
different technologies. A fellow PCS student has been blogging a…]]></description><link>http://katieleonard.ca/blog/2013/2013-06-15-blogging-with-jekyll-bootstrap/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2013/2013-06-15-blogging-with-jekyll-bootstrap/</guid><pubDate>Sat, 15 Jun 2013 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Building a portfolio has been a lot of fun and has required a couple of
different technologies. A fellow PCS student has been blogging a long time,
and he suggested using Jekyll in combination with github pages. What a
fantastic gem! I found an even more awesome one at &lt;a href=&quot;http://jekyllbootstrap.com/&quot;&gt;jekyll-bootstrap&lt;/a&gt;.&lt;!--more--&gt;&lt;/p&gt;
&lt;p&gt;Now I am enjoying the power of bootstrap along with the ease of jekyll.&lt;/p&gt;
&lt;p&gt;To create a post&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ rake post title=&quot;Hello World&quot;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;To create a new page:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ rake page name=&quot;pages/about&quot;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Couldn’t be simpler for a beginning blogger.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[I admit it, I love TDD]]></title><description><![CDATA[This week @PDXcodeschool we jumped into TDD using minitest/autorun. I have
used RSpec in the past, and loved the way it let me manage the…]]></description><link>http://katieleonard.ca/blog/2013/2013-06-14-TDD-is-the-way-to-be/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2013/2013-06-14-TDD-is-the-way-to-be/</guid><pubDate>Fri, 14 Jun 2013 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;This week @PDXcodeschool we jumped into TDD using minitest/autorun. I have
used RSpec in the past, and loved the way it let me manage the logic of my project.
I love that ruby has a built in framework — so easy to use!&lt;/p&gt;
&lt;!--more--&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Use specs to rough out project logic&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;describe &quot;Car&quot; do
it &apos;should have a color&apos;
it &apos;should have a make&apos;
it &apos;should have a unique serial number&apos;
it &apos;should get a new serial number when it gets stolen&apos;
it &apos;should accept passengers&apos;
it &apos;should not accept more than 3 passengers&apos;
end&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;All of these tests will be skipped until they are followed by a do…end block.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Take one test at a time and write the code to make it pass&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;describe &quot;Car&quot; do
it &apos;should have a color&apos; do
car = Car.new(&quot;black&quot;)
car.color.must_equal &quot;black&quot;
end
...
end&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;If your tests exercise the project well enough, you end up with really tight code.
More of a lasagna noodle than spaghetti!&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[A Flash of Understanding]]></title><description><![CDATA[My page wouldn’t flash the user. Trundling along the Hartl railstutorial, I needed to write some logic to allow a user to update their…]]></description><link>http://katieleonard.ca/blog/2013/2013-07-13-a-flash-of-understanding/</link><guid isPermaLink="false">http://katieleonard.ca/blog/2013/2013-07-13-a-flash-of-understanding/</guid><pubDate>Sat, 13 Apr 2013 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;My page wouldn’t flash the user.&lt;/p&gt;
&lt;p&gt;Trundling along the &lt;a href=&quot;http://ruby.railstutorial.org/chapters/updating-showing-and-deleting-users?version=4.0#top&quot;&gt;Hartl railstutorial&lt;/a&gt;, I needed to write some logic to allow a user to update their information.&lt;/p&gt;
&lt;p&gt;As a &lt;a href=&quot;http://www.katieleonard.ca/tdd/testing/2013/06/14/TDD-is-the-way-to-be/&quot;&gt;loyal TDD-er&lt;/a&gt;, I wrote a test to check that users see a success message if they are able to update their infomation:&lt;!--more--&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;describe &quot;updating with valid information&quot; do
  let(:new_name) { &quot;New Name&quot; }
  let(:new_email) { &quot;new@example.com&quot; }
  before do
    fill_in &quot;Name&quot;, with: new_name
    fill_in &quot;Email&quot;, with: new_email
    fill_in &quot;Password&quot;, with: user.password
    fill_in &quot;Confirm Password&quot;, with: user.password
    click_button &quot;Save changes&quot;
  end
  it { should have_selector(&apos;div.alert.alert-success&apos;) }
end&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;As expected, the tests should fail until I am able to log in.&lt;/p&gt;
&lt;p&gt;Since the Rails4 user scaffold comes with some nifty built in methods, I thought it would be easy to adapt them for my own ends:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ruby&quot;&gt;&lt;pre class=&quot;language-ruby&quot;&gt;&lt;code class=&quot;language-ruby&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# PATCH/PUT /users/1&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# PATCH/PUT /users/1.json&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token method-definition&quot;&gt;&lt;span class=&quot;token function&quot;&gt;update&lt;/span&gt;&lt;/span&gt;
  respond_to &lt;span class=&quot;token keyword&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt;format&lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;@user&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;update&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;user_params&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      format&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;html &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; redirect_to &lt;span class=&quot;token variable&quot;&gt;@user&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token symbol&quot;&gt;notice&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Profile updated.&apos;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
      format&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;json &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; head &lt;span class=&quot;token symbol&quot;&gt;:no_content&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt;
      format&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;html &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; render action&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&apos;edit&apos;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
      format&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;json &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; render json&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;@user&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;errors&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token symbol&quot;&gt;status&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token symbol&quot;&gt;:unprocessable_entity&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I modify the line 5 of the user controller to change the “notice” message to a “success” message:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ruby&quot;&gt;&lt;pre class=&quot;language-ruby&quot;&gt;&lt;code class=&quot;language-ruby&quot;&gt;format&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;html &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; redirect_to &lt;span class=&quot;token variable&quot;&gt;@user&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token symbol&quot;&gt;success&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Profile updated&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Seems reasonable, but my test for the flash message is still failing. Why won’t my page flash the user?!&lt;/p&gt;
&lt;p&gt;Quick as a flash, I asked &lt;a href=&quot;https://itunes.apple.com/us/app/dash-docs-snippets/id458034879?mt=12&quot;&gt;Dash&lt;/a&gt; about FlashHash.&lt;/p&gt;
&lt;p&gt;Lo, and behold! Notice and alert are built-in flash tags, but success is nowhere to be found. How can I express the satisfaction of &lt;code class=&quot;language-text&quot;&gt;SUCCESS!!&lt;/code&gt; with a tag as mundane as notice:?&lt;/p&gt;
&lt;p&gt;Thanks to &lt;a href=&quot;http://en.wikipedia.org/wiki/Duck_typing&quot;&gt;duck-typing&lt;/a&gt; (if it walks like a duck and quacks like a duck, it is probably a hash.. right?) we can add our spiffy &lt;code class=&quot;language-text&quot;&gt;success:&lt;/code&gt; tag to flash, and share the appropriate level of enthusiasm with our users:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ruby&quot;&gt;&lt;pre class=&quot;language-ruby&quot;&gt;&lt;code class=&quot;language-ruby&quot;&gt;format&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;html &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; redirect_to &lt;span class=&quot;token variable&quot;&gt;@user&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token symbol&quot;&gt;flash&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token symbol&quot;&gt;success&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Profile updated&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;All tests are green, and today I learned that flash is&lt;/p&gt;
&lt;p&gt;Awesome&lt;/p&gt;</content:encoded></item></channel></rss>