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

  <title>Phillip's Notes</title>
  <link href="https://ptx.sh/atom.xml" rel="self"/>
  <link href="https://ptx.sh"/>
  <updated>2026-04-14T08:34:00-05:00</updated>
  <id>https://ptx.sh</id>
  <author>
    <name>Phillip Ridlen</name>
    <email>phil@ptx.sh</email>
  </author>

  <icon>https://ptx.sh/images/favicon/favicon-180.png</icon>
  <logo>https://ptx.sh/images/phillipridlen.png</logo>

  
  <entry>
    <title>Tasty Blended Coffee Treat for 50¢</title>
    <link href="https://ptx.sh/notes/food/2026/04/14/tasty-blended-coffee-treat-for-50-cents/"/>
    <updated>2026-04-14T08:34:00-05:00</updated>
    <id>https://phillipridlen.com/notes/id/H27XJGNNMYUR89RBNG1SN20Q2W</id>
    <content type="html">
      &lt;p&gt;&lt;img src="blended-coffee.png" alt="illustration of an frozen blended coffee beverage in a mason jar with plastic bendy straw"&gt;&lt;/p&gt;

&lt;p&gt;Do you like Frappucino®s&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote" rel="footnote" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt; from Starbucks? Do you &lt;em&gt;not&lt;/em&gt; like how expensive
they are? Here’s a recipe for a tasty blended coffee treat that costs less than
50¢ to make:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;1 cup milk&lt;/li&gt;
  &lt;li&gt;5 tbsp sugar&lt;/li&gt;
  &lt;li&gt;1 tbsp instant coffee&lt;/li&gt;
  &lt;li&gt;1 cup ice&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Blend and enjoy!&lt;/p&gt;

&lt;div class="footnotes" role="doc-endnotes"&gt;
  &lt;ol&gt;
    &lt;li id="fn:1"&gt;

      &lt;p&gt;&lt;strong&gt;Frappuccino®&lt;/strong&gt; is a registered trademark of &lt;strong&gt;Starbucks Corporation.&lt;/strong&gt;
This site is not affiliated with, endorsed by, or sponsored by Starbucks
Corporation. &lt;a href="#fnref:1" class="reversefootnote" role="doc-backlink"&gt;↩︎&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
&lt;img src="https://analytics.ptx.sh/p/SjOB3oKbb?id=H27XJGNNMYUR89RBNG1SN20Q2W&amp;url=%2Fnotes%2Ffood%2F2026%2F04%2F14%2Ftasty-blended-coffee-treat-for-50-cents%2F" alt="" /&gt;
    </content>
  </entry>
  
  <entry>
    <title>AI is making things better, but worse</title>
    <link href="https://ptx.sh/notes/programming/2026/04/11/ai-is-making-things-better-but-worse/"/>
    <updated>2026-04-11T20:45:00-05:00</updated>
    <id>https://phillipridlen.com/notes/id/2YG8VYNN5HU6XM0GP6DBFZO8Z0</id>
    <content type="html">
      &lt;p&gt;We thought AI was going to make life easier, giving us time back by automating
away the monotonous work. But just like the Industrial Revolution, factory
automation, and robots didn’t lead to giving workers a life of ease and luxury,
knowledge work automation through agentic and generative AI is no Caribbean
vacation; it tends to leave us with dopamine “crashes” and mental fatigue. Both
of those lead to increased brain fog, exhaustion, and irritability.&lt;/p&gt;

&lt;p&gt;Before we go any further, let me preface what follows with the caveat that I do
not consider myself a neuroscience enthusiast, let alone a professional. This is
my rudimentary understanding, and it is likely missing nuance or is simply
incorrect. If you have more experience in this field than me, and you find my
explanations lacking, please &lt;a href="mailto:phil@ptx.sh?subject=Re:%20AI%20is%20making%20things%20better,%20but%20worse"&gt;send me an email&lt;/a&gt; and I will update this
post accordingly.&lt;/p&gt;

&lt;p&gt;When you click the button to send off the generative AI to go do its work, it’s
a little bit like pulling the lever of a slot machine. What you get out of it
could be terrible, or it could be great. Life changing, even. More often than
not, it’s just good enough that we feel like we are winning: The report numbers
are crunched, the software is written, the email is polished, the artwork is
generated—in quantities far beyond what we could previously accomplish. But
there is a cost. We pull the lever, getting close to what we really want, but
never quite reaching the peak of excellence. It’s good enough that we go back
for more, but not satisfying enough to get us to quit. And so we pull the lever
again, and again, and again.&lt;/p&gt;

&lt;p&gt;&lt;img src="slot-machine.png" alt='Exhausted and depressed man at a slot machine called "AI Generation"'&gt;&lt;/p&gt;

&lt;figcaption&gt;
  Generative AI work is a lot like a slot machine—sometimes you hit it big.
&lt;/figcaption&gt;

&lt;p&gt;My understanding is that this is called a variable reward schedule&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote" rel="footnote" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt;. After a
prolonged period of operating in this mode, our brains calibrate themselves to
this, and the rewards for normal routine activities are dull by comparison.
Irritability, exhaustion, lack of motivation, and poor or impulsive
decision-making set in, and it takes time to recharge and let our brains
calibrate back to normal before we can be decent human beings again.&lt;/p&gt;

&lt;p&gt;A related second problem is simply mental fatigue. When you make a series of
high-impact decisions, perform qualitative analysis on a large volume of
content&lt;sup id="fnref:2"&gt;&lt;a href="#fn:2" class="footnote" rel="footnote" role="doc-noteref"&gt;2&lt;/a&gt;&lt;/sup&gt;, or attempt to multitask&lt;sup id="fnref:3"&gt;&lt;a href="#fn:3" class="footnote" rel="footnote" role="doc-noteref"&gt;3&lt;/a&gt;&lt;/sup&gt;, it has a similar effect, at least in
my experience. I know less about the biological and psychological mechanisms on
this one, but they’re real.&lt;/p&gt;

&lt;p&gt;AI work involves all of these leading causes of mental fatigue. Entrepreneur and
software engineer Steve Yegge, in his widely circulated Medium post,
&lt;a href="https://steve-yegge.medium.com/the-ai-vampire-eda6e4f07163"&gt;The AI Vampire&lt;/a&gt;,
writes:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;I’ve argued that AI has turned us all into Jeff Bezos, by automating the easy
work, and leaving us with all the difficult decisions, summaries, and
problem-solving. I find that I am only really comfortable working at that pace
for short bursts of a few hours once or occasionally twice a day, even with
lots of practice. … I’m convinced that 3 to 4 hours is going to be the sweet
spot for the new workday. … Assume that exhaustion is the norm. Building
things with AI takes a lot of human energy.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Because we automate the busy work, it doesn’t give our brains time to recharge
from the fatigue. Furthermore, we’re constantly switching from task to task as
our agents happily work away. I’m currently learning how to protect that energy
and keep some reserve in the tank for my family during evenings and weekends.&lt;/p&gt;

&lt;p&gt;You could try to sustain your multiplied output at full capacity and end up
disconnected from reality, exhausted, angry, and unhappy. I’ve recently been
filling my evenings with LLM conversations, music generation, and vibe-coded
side projects only to yell at my kids and say rude things to my wife because my
brain is too tapped out to be compassionate.&lt;/p&gt;

&lt;p&gt;&lt;img src="numb.png" alt="Illustration of a man laying on the couch, staring at the ceiling, static on the TV"&gt;&lt;/p&gt;

&lt;figcaption span="markdown"&gt;
  Too tapped out to be compassionate.
&lt;/figcaption&gt;

&lt;p&gt;We have to find the right balance between productivity and rest—both at work and
at home. We can’t go full bore at work and then expect to be able to have the
energy and motivation to accomplish the things we need to get done at home. What
is that balance? It obviously will be different for everyone. But we have to be
intentional about it. We can’t just let it happen to us, or we’ll burn out and
be left with nothing.&lt;/p&gt;
&lt;div class="footnotes" role="doc-endnotes"&gt;
  &lt;ol&gt;
    &lt;li id="fn:1"&gt;

      &lt;p&gt;B. F. Skinner showed that when rewards come after an unpredictable number of
tries (he called it a
&lt;a href="https://en.wikipedia.org/wiki/B._F._Skinner#Schedules_of_reinforcement"&gt;variable ratio schedule&lt;/a&gt;),
people keep going much longer. Because the next reward might come at any
time, it encourages repeated behavior. This is why slot machines, doom
scrolling, social media reactions, and now generative AI are so addicting.
This is different from the variable interval schedule, which is time-based.
Because the number of tries is proportional to the number of rewards—albeit
variably—the variable ratio schedule is much more likely to increase
engagement. &lt;a href="#fnref:1" class="reversefootnote" role="doc-backlink"&gt;↩︎&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id="fn:2"&gt;

      &lt;p&gt;John Sweller’s Cognitive Load Theory, developed in the 1980s, is helpful
here. It’s the idea that we have a limited capacity for working memory, and
when we exceed that, it increases stress, reduces learning, and our
attention fragments. It’s the same reason a small code change is easier to
review than a large one. Generative and agentic AI defaults to producing
large changes. There are probably ways that we can tune our context so that
the models return smaller changes at a time, but then we drift further into
rapid task switching (see &lt;a href="#fn:3"&gt;footnote #3&lt;/a&gt;) and reduce our overall
productivity. &lt;a href="#fnref:2" class="reversefootnote" role="doc-backlink"&gt;↩︎&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id="fn:3"&gt;

      &lt;p&gt;Psychologists generally distinguish true multitasking from rapid task
switching. When people switch back and forth between tasks, performance
slows and errors tend to increase because the brain has to reorient each
time rather than doing both demanding tasks at once. Furthermore, while the
research is still in the early stages, there are indications that the
&lt;a href="https://pmc.ncbi.nlm.nih.gov/articles/PMC11543232/"&gt;negative long-term effects include weakened memory, reduced concentration
and increased anxiety&lt;/a&gt;. &lt;a href="#fnref:3" class="reversefootnote" role="doc-backlink"&gt;↩︎&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
&lt;img src="https://analytics.ptx.sh/p/SjOB3oKbb?id=2YG8VYNN5HU6XM0GP6DBFZO8Z0&amp;url=%2Fnotes%2Fprogramming%2F2026%2F04%2F11%2Fai-is-making-things-better-but-worse%2F" alt="" /&gt;
    </content>
  </entry>
  
  <entry>
    <title>Vibe coding a native macOS app to edit my blog</title>
    <link href="https://ptx.sh/notes/programming/2025/12/29/vibe-coding-a-native-macos-app-to-edit-my-blog/"/>
    <updated>2025-12-29T23:22:00-06:00</updated>
    <id>https://phillipridlen.com/notes/id/YVB0TMC12GP2AQ5YDUAII6NTLR</id>
    <content type="html">
      &lt;p&gt;I have an awesome new editor for my website. It’s a native macOS SwiftUI app
that I can boot up on my Mac and write and edit posts. I don’t know Swift. And I
don’t know the SwiftUI API. To me this is the perfect candidate for blind vibe
coding. It’s a totally offline, unsupported app that improves my quality of life
and inspires me to write, because it feels… well, it just feels &lt;em&gt;good&lt;/em&gt;.&lt;/p&gt;

&lt;video src="admin.mp4" autoplay="" loop="" muted="" playsinline=""&gt;&lt;/video&gt;

&lt;figcaption&gt;
  Collapsible sidebar, date pickers, posts sorted by date and grouped
  by month.
&lt;/figcaption&gt;

&lt;p&gt;It’s not perfect. And I have lots of ideas for improvements. It will just keep
getting better and better. If you’re interested, you can look at the source
&lt;a href="https://github.com/philtr/blog-admin"&gt;in the standalone &lt;code&gt;philtr/blog-admin&lt;/code&gt; repo&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I’ve been using the OpenAI Codex CLI for my personal projects, and I find it
roughly equivalent in features and quality to Amazon’s Kiro CLI that is provided
to me at work, which uses the Anthropic models. I think I prefer Codex just a
hair; it does a better job understanding my poor job of explaining what I want
it to do, and asks more clarifying questions if my instructions are too vague.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;UPDATE (2026-04-17):&lt;/strong&gt; I split the app out into its own repository at
&lt;a href="https://github.com/philtr/blog-admin"&gt;&lt;code&gt;philtr/blog-admin&lt;/code&gt;&lt;/a&gt;. It still targets
the same content layout in this site repo, but it is now developed and versioned
separately.&lt;/p&gt;
&lt;img src="https://analytics.ptx.sh/p/SjOB3oKbb?id=YVB0TMC12GP2AQ5YDUAII6NTLR&amp;url=%2Fnotes%2Fprogramming%2F2025%2F12%2F29%2Fvibe-coding-a-native-macos-app-to-edit-my-blog%2F" alt="" /&gt;
    </content>
  </entry>
  
  <entry>
    <title>Wanting Back What We Can Never Have</title>
    <link href="https://ptx.sh/notes/life/2025/12/27/wanting-back-what-we-can-never-have/"/>
    <updated>2025-12-27T09:00:00-06:00</updated>
    <id>https://phillipridlen.com/notes/id/IFY0BJCBG6696QLVMYWDYUM8A2</id>
    <content type="html">
      &lt;p&gt;&lt;img src="family-room-pc.png" alt="Illustration of a 1990s family room with a PC"&gt;&lt;/p&gt;

&lt;p&gt;On any given September afternoon in the late 1990s, you might find me racing
home from school on my bicycle. I was overweight, and not a particularly strong
cyclist. The way to my house from Sheridan Green Elementary (which, I learned
recently, was
&lt;a href="https://www.westminsterwindow.com/news/government-politics/article_715ec394-a453-4afb-8fc1-c5f8e3d14b37.html"&gt;demolished and will soon be replaced with a city park&lt;/a&gt;)
was mostly flat, until you got to the hill on 112th Place, which didn’t really
look much at all like a hill until you tried to ride your bike up it, and, upon
reaching the summit, you found yourself out of breath and your legs all wobbly.&lt;/p&gt;

&lt;p&gt;&lt;img src="112th.png" alt='The "hill" on 112th Place'&gt;&lt;/p&gt;

&lt;figcaption&gt;
  It was &lt;em&gt;mostly&lt;/em&gt; flat.
&lt;/figcaption&gt;

&lt;p&gt;After catching my breath, greeting my mom, and having a quick snack, I’d ask
permission to use our family’s phone line to connect to the internet to check my
email and play an online match of &lt;em&gt;Age of Empires&lt;/em&gt;, firing up our trusty 56K
dial-up modem connected to the family computer. The «familiar screech of the
modem making contact» with the digital universe was like the secret knock on the
door to a magical world, where nothing was impossible. It was the Information
Age, and we optimistically looked forward to the dawning of a new millennium
that would keep us more informed, more connected, more efficient, than ever
before.&lt;/p&gt;

&lt;p&gt;&lt;img src="doomscroll.png" alt="Illustration of me doomscrolling"&gt;&lt;/p&gt;

&lt;figcaption&gt;
  «The internet followed me out of the family room and into my
  pocket.»
&lt;/figcaption&gt;

&lt;p&gt;The internet kept getting better. Our connections kept getting faster. First, we
installed a dedicated second phone line in our house so we wouldn’t tie up the
line for phone calls. Before long, we had DSL. I could download a song from
&lt;a href="https://web.archive.org/web/20020531114503/http://mp3.com/"&gt;mp3.com&lt;/a&gt; in mere
minutes, not hours. ICQ and AOL Instant Messenger connected me to school and
church friends, but also my friends from around the world. I had several guys I
chatted with often whom I had met on a youth group mission trip. The
&lt;a href="https://www.myinstants.com/en/instant/door-open-aim-93903/"&gt;opening door sound&lt;/a&gt;
of my friends coming online gave a rush of excitement—I didn’t even have to
leave my room or stop what I was doing to talk to my friends.&lt;/p&gt;

&lt;p&gt;Slowly, the center of social life faded from schools, clubs, and churches—it was
now Myspace, Facebook, and Twitter. My addiction became asynchronous, scrolling
for the next cool post while waiting for the reactions and comments on my own.
Before I knew it, and with my full consent, «the internet followed me out of the
family room and into my pocket» with the advent of the smartphone, which acted
as an accelerant for all the best—and worst—things the internet had to offer. I
didn’t stop to consider the consequences.&lt;/p&gt;

&lt;p&gt;&lt;img src="information-age.png" alt="Illustration of me overwhelmed by information, piles of papers on my desk"&gt;&lt;/p&gt;

&lt;figcaption&gt;
  It was the Information Age, but we didn't stop to consider the consequences.
&lt;/figcaption&gt;

&lt;p&gt;The Information Age failed to deliver on its promise. The flood of news,
awareness, and connection around the world combined with addiction only led to
more anxiety and more wasted time. Keeping up with every latest news story,
every current internet trend and meme, has become increasingly exhausting. Those
entering adulthood right now have never known a world without an omni-present
high-speed connection to &lt;em&gt;anything and everything&lt;/em&gt;. They’ve never tasted the
ancient peace of living offline.&lt;/p&gt;

&lt;p&gt;It didn’t feel remarkable at the time. The boredom, the freedom to let your mind
wander without constant digital input. Scanning magazine covers and candy bars
in the grocery store checkout line. Waiting for your favorite television program
to come on the air. It all just felt &lt;em&gt;normal&lt;/em&gt;. And now that peace is gone.&lt;/p&gt;

&lt;p&gt;&lt;img src="dumpster.png" alt="Illustration of me looking at my old PC in the dumpster"&gt;&lt;/p&gt;

&lt;figcaption&gt;It is tempting to give into the nostalgia.&lt;/figcaption&gt;

&lt;p&gt;I often catch myself wishing for that earlier version of the internet—the one I
could more easily log off, go outside, wonder, and be bored, and despite
technically being less connected, felt more real and satisfying. It is tempting
to give in to the nostalgia. But here’s the deal: those times can’t come back.
And maybe they &lt;em&gt;shouldn’t&lt;/em&gt;. «The world is too connected, too efficient, too
transparent now.» There’s no going back. No matter how much we long for the days
of intermittent connection, the ship is too large to steer.&lt;/p&gt;

&lt;p&gt;But beyond that, here’s the question that scares me most: &lt;em&gt;What if the peace and
slower pace of life I remember from my childhood never really existed in the
first place?&lt;/em&gt; As we age, we look on the past with rose-colored glasses. The past
seems simpler now, but it was fraught with its own anxiety. Got stranded on the
side of the road in the middle of nowhere? Hope that a car passes by, is willing
to stop, and is not a serial killer. We had to rely on the details that the news
media felt were important, unable to do our own research. If you had an unusual
hobby, it was more difficult to find others who shared your interests.&lt;/p&gt;

&lt;p&gt;&lt;img src="stranded.png" alt="Illustration of me stranded in the desert with a broken down car"&gt;&lt;/p&gt;

&lt;figcaption&gt;Counting on the kindness of strangers.&lt;/figcaption&gt;

&lt;p&gt;And if I’m being truly honest, I never really lived that slower pace. It’s a
false memory of a time before my own. The internet grew up with me, and I grew
up with the internet. I was relatively young when the internet became
ubiquitous, and I was still in college when I got my first smartphone.&lt;/p&gt;

&lt;p&gt;There’s also some good in that connection. It pays my salary, yes—but there are
tangible benefits to having the wealth of the knowledge of humanity at your
fingertips. I don’t have to brave the busy aisles of a grocery store and wonder
if they’ll have what I need in stock. I can order replacement parts for my home
appliances and have them arrive in the mail within a day or two, at half the
cost of the manufacturer’s part. I can purchase a book and be reading it on my
tablet within seconds.&lt;/p&gt;

&lt;p&gt;I don’t think what I &lt;em&gt;really&lt;/em&gt; miss is the alien sounds of the dial-up modem or
waiting for my computer to boot up as the spinning hard drive skipped across bad
sectors. I think what I miss is the boundaries and constraints that came
naturally with the limitations of the technology. Boundaries between the real
and digital world, and boundaries between contexts. It all collapsed into one–
«work, family, news, entertainment, faith, and politics, all on the same screen
in the same feed.» The boundaries gave life rhythm and meaning, intentionality
and purpose, and now daily life has been reshaped at its foundation.&lt;/p&gt;

&lt;p&gt;&lt;img src="shutting-down.png" alt="Illustration of a 1990s desktop PC in its shutdown sequence"&gt;&lt;/p&gt;

&lt;figcaption&gt;
  We have to take control of the technology so it does not take control of us.
&lt;/figcaption&gt;

&lt;p&gt;Where do I go from here? Grieving the loss of what we once had is the first step
to moving on. We have to understand the new foundation for living in the digital
world, and define the way we will use that technology rather than letting it
define us. We have to take control of the technology so it does not take control
of us.&lt;/p&gt;

&lt;p&gt;We need to establish rhythms of life that bring us in and out of the online
world. Weekly events like church, clubs, workout groups, or neighborhood
barbecues can pull us out of our digital haze and foster the offline connection
we crave.&lt;/p&gt;

&lt;p&gt;Maybe it’s OK to keep your world small. Maybe it’s OK to ignore the news
headlines and political ranting on social media. Maybe it’s better to let
friendships drift apart when you move away rather than try to keep up with it
all.&lt;/p&gt;

&lt;p&gt;As for me? Being mindful of my screen time and using apps that nudge me in the
right direction&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote" rel="footnote" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt; has palpably increased my satisfaction and enjoyment of both
my family time and computing time. I’m going to put down my phone and make the
world a little smaller.&lt;/p&gt;

&lt;p&gt;&lt;img src="playing-with-kids.png" alt="Illustration of me playing with my kids and ignoring my phone"&gt;&lt;/p&gt;

&lt;figcaption&gt;
  I'm going to put down my phone and make the world a little smaller.
&lt;/figcaption&gt;

&lt;hr&gt;

&lt;aside&gt;
  &lt;strong&gt;AI Disclaimer:&lt;/strong&gt; The idea and basic structure for this post came out of a
  “conversation” I had with ChatGPT. However, the words are all mine. During the
  writing of this post, I occasionally consulted AI for help with a transition or
  clunky phrase. For full transparency, any phrases directly produced by AI have
  been «marked with double guillemets». The illustrations for this article were
  generated with &lt;a href="https://drawthings.ai"&gt;Draw Things&lt;/a&gt; using the “Qwen Image Edit 2509” model.
&lt;/aside&gt;

&lt;div class="footnotes" role="doc-endnotes"&gt;
  &lt;ol&gt;
    &lt;li id="fn:1"&gt;

      &lt;p&gt;Currently, I’m using &lt;a href="https://www.bepresentapp.com/"&gt;Be Present&lt;/a&gt;. It has a
huge advantage over iOS’s built-in ScreenTime controls, and for me, it
strikes the right balance of restriction and flexibility. In the last month,
I’ve reduced my smartphone usage by over 50%. If you’re looking for
something to encourage healthy screen time habits, check it out! This is how
we reclaim peace and sanity as culture. &lt;a href="#fnref:1" class="reversefootnote" role="doc-backlink"&gt;↩︎&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
&lt;img src="https://analytics.ptx.sh/p/SjOB3oKbb?id=IFY0BJCBG6696QLVMYWDYUM8A2&amp;url=%2Fnotes%2Flife%2F2025%2F12%2F27%2Fwanting-back-what-we-can-never-have%2F" alt="" /&gt;
    </content>
  </entry>
  
  <entry>
    <title>Grace in Gratitude</title>
    <link href="https://ptx.sh/notes/christianity/2020/11/24/grace-in-gratitude/"/>
    <updated>2020-11-24T09:00:00-06:00</updated>
    <id>https://phillipridlen.com/notes/id/U9WGZCZW3FB8A2XG4MKNR9HQ10</id>
    <content type="html">
      &lt;p&gt;I can’t tell you how many times I’ve received a gift and meant to say thank you,
whether in person, over the phone, or with a note, and completely forgotten. By
not making a priority of letting them know their gift was appreciated, I am
being ungrateful. This is a sin that can easily slip into habit without notice.&lt;/p&gt;

&lt;p&gt;Look at the lepers who were healed by Jesus on His way past Samaria in Luke
17:11-19. Ten men received miraculous healing, yet only one returned to give
thanks and praise to the One who healed him.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;[The ten lepers said,] “Jesus, Master, have mercy on us.” When he saw them he
said to them, “Go and show yourselves to the priests.” And as they went they
were cleansed. Then one of them, when he saw that he was healed, turned back,
praising God with a loud voice; and he fell on his face at Jesus’ feet, giving
him thanks. Now he was a Samaritan. Then Jesus answered, “Were not ten
cleansed? Where are the nine? Was no one found to return and give praise to
God except this foreigner?” And he said to him, “Rise and go your way; your
faith has made you well.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Your faith has made you well.&lt;/strong&gt; I think the interesting thing here is that
statement here is true of &lt;em&gt;all ten&lt;/em&gt; men, not just the one who returned. They
were each given a gift, yet only one was marked by true gratitude. I like to
imagine that the other ten were indeed thankful, but they were so excited to be
healed that they ran off to the priests to get a clean bill of health, ran home
to hug their families, and carried on with their lives. It’s like the kid on
Christmas morning who’s so excited about his gift that he tears into it and
begins playing with it, but he’s so preoccupied with the gift that he forgets to
show gratitude.&lt;/p&gt;

&lt;p&gt;Jesus continues to show grace to the ungrateful, but the one who returns the
praise back to Him has a richer understanding of the grace he received. This
Thanksgiving I’m most grateful for the grace God has given me in every area of
life, even (especially?) the areas where He’s growing me.&lt;/p&gt;
&lt;img src="https://analytics.ptx.sh/p/SjOB3oKbb?id=U9WGZCZW3FB8A2XG4MKNR9HQ10&amp;url=%2Fnotes%2Fchristianity%2F2020%2F11%2F24%2Fgrace-in-gratitude%2F" alt="" /&gt;
    </content>
  </entry>
  
  <entry>
    <title>Getting Unstuck</title>
    <link href="https://ptx.sh/notes/life/2020/11/23/getting-unstuck/"/>
    <updated>2020-11-23T09:00:00-06:00</updated>
    <id>https://phillipridlen.com/notes/id/LHKD7A403W1OMJ6TNQPFGJQZBH</id>
    <content type="html">
      &lt;p&gt;I want to write, more but I’m not sure what to write about. My &lt;a href="https://phillipridlen.com/notes/"&gt;blog&lt;/a&gt; is all
over the place and lacks a singular focus, because my interests are varied and
lack a singular focus. Some ideas I’ve had over the years:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Christianity, both theology and the practical outworkings of that theology&lt;/li&gt;
  &lt;li&gt;Programming&lt;/li&gt;
  &lt;li&gt;Music or musical instruments and musicianship&lt;/li&gt;
  &lt;li&gt;Apple products&lt;/li&gt;
  &lt;li&gt;Tasting delicious food and trying new restaurants and recipes&lt;/li&gt;
  &lt;li&gt;Traveling together with my family&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;However, if you’ll notice, nothing’s been posted on this blog since January of
2018—nearly three years! I’ve discovered I like the idea of writing more than I
acutally enjoy writing. There is a certain romance to the idea of being able to
sit down and write a thousand—or five thousand—words that eloquently string
together a point that simultaneously resonates with and challenges my audience.
There is a reality check than needs to happne here. In high school and college,
I had difficulty writing more than a few thousand words on topics I’d thoroughly
reasearched and was passionate about. I’m not sure how I expect myself to be
able to wirte that on topics in which I have much less knowledge and expertise.&lt;/p&gt;

&lt;p&gt;As an effort to unstick myself, I’m going to be OK with writing things that
never get published. I’m going to be OK with writing things that only consist of
a few hundred or even a few dozen words. The idea is that the more I do it, the
more I make a habit out of putting my thoughts to pen and paper (or pixels and
bits), the more I will feel comfortable expressing my ideas, interests, and
expertise in written word.&lt;/p&gt;

&lt;p&gt;I want to say, “expect many more new blog posts from me in 2021.” But I know how
that has gone in the past, with interest waning with the moon and passion for
writing fizzling out. And that’s okay, too. I sit behind a drumset every few
weeks to remind myself how difficult it is and how I’m more in love with the
idea of playing drums than I am with putting in the hard work and effort to
learn to play them well. Perhaps this will be a catalyst for writing more, but
it may also be a “sitting behind the drumset” moment.&lt;/p&gt;

&lt;img src="https://analytics.ptx.sh/p/SjOB3oKbb?id=LHKD7A403W1OMJ6TNQPFGJQZBH&amp;url=%2Fnotes%2Flife%2F2020%2F11%2F23%2Fgetting-unstuck%2F" alt="" /&gt;
    </content>
  </entry>
  
  <entry>
    <title>Book Review: You Need a Budget by Jesse Mecham</title>
    <link href="https://ptx.sh/notes/life/2018/01/03/book-review-you-need-a-budget/"/>
    <updated>2018-01-03T09:00:00-06:00</updated>
    <id>https://phillipridlen.com/notes/id/MBV3XU4O38KT76CSBTRX9UYTCP</id>
    <content type="html">
      &lt;p&gt;I reviewed &lt;em&gt;You Need a Budget&lt;/em&gt; by Jesse Mecham &lt;a href="https://www.amazon.com/gp/customer-reviews/R2ONOZ0DKXYYQL/ref=cm_cr_getr_d_rvw_ttl?ie=UTF8&amp;amp;ASIN=0062567586"&gt;on Amazon&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;While I am a huge fan of the YNAB product, and have been using it actively for
several years, I half expected this book to be a thinly veiled advertisement
to purchase his tool and convert to a paying customer. Mecham only mentions
YNAB in passing as part of the real life examples, and puts a link to it in
the appendix.&lt;/p&gt;

  &lt;p&gt;This is not a book about how to use YNAB. This is a book to convince you first
that the budgeted life is a better life, and secondly that a budget is
something YOU can do.&lt;/p&gt;

  &lt;p&gt;Mecham’s Four Rules are presented in plain English using words that anyone can
understand. These four rules really get to the heart of why You Need A Budget.
Other financial advice will tell you what and how, YNAB is focused on the why
(with a little bit of how).&lt;/p&gt;

  &lt;p&gt;Even though I was already familiar with the Four Rules, reading this book gave
me a renewed vision and helped me realize I was looking at my budget as a
“what,” but I needed to examine the “why”.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;img src="https://analytics.ptx.sh/p/SjOB3oKbb?id=MBV3XU4O38KT76CSBTRX9UYTCP&amp;url=%2Fnotes%2Flife%2F2018%2F01%2F03%2Fbook-review-you-need-a-budget%2F" alt="" /&gt;
    </content>
  </entry>
  
  <entry>
    <title>Adam Asks: Parity, Blocks, and Enumerators. Oh My!</title>
    <link href="https://ptx.sh/notes/programming/2017/03/10/adam-asks-parity-blocks-enumerators-oh-my/"/>
    <updated>2017-03-10T09:00:00-06:00</updated>
    <id>https://phillipridlen.com/notes/id/QXV1IIX12N63QN9GZMMLVDAFPG</id>
    <content type="html">
      &lt;p&gt;Adam is a friend of mine learning to program. Every once in a while, he’ll send
me a bit of code to look over to learn how he might be able to do it better. The
latest one was an exercise involving splitting an array based on the parity of
the number, that is to say whether the number is even or odd.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Can you check this over for me?&lt;/p&gt;

  &lt;p&gt;Method that takes an array as argument, counts and displays the odds and evens
from the array. It works as expected—I’m just looking for best
practices.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Here is Adam’s original code:&lt;/p&gt;

&lt;div class="language-ruby highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;numbereven&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;numarr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;neven&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
  &lt;span class="n"&gt;nodd&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
  &lt;span class="n"&gt;narray&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
  &lt;span class="n"&gt;narrayo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;

  &lt;span class="n"&gt;numarr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
      &lt;span class="n"&gt;neven&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
      &lt;span class="n"&gt;narray&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;
      &lt;span class="n"&gt;nodd&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
      &lt;span class="n"&gt;narrayo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"There are &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;neven&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; even numbers and &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;nodd&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; odd numbers in this array."&lt;/span&gt;
  &lt;span class="nb"&gt;print&lt;/span&gt; &lt;span class="s2"&gt;"Evens: "&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;narray&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
  &lt;span class="nb"&gt;print&lt;/span&gt; &lt;span class="s2"&gt;"Odds: "&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;narrayo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;my_array&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1001&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;numbereven&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;my_array&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;I may have scared him off with the sheer volume of my reply. I wrote a bit how I
would write it, another way to write it, and why I wouldn’t write it that
way.&lt;/p&gt;

&lt;h2 id="how-i-would-write-it"&gt;How I Would Write It&lt;/h2&gt;

&lt;div class="language-ruby highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;parity_counts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;evens&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;select&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;even?&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="n"&gt;odds&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;numbers&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;evens&lt;/span&gt;

  &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"There are &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;evens&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;size&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; even numbers and &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;odds&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;size&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
       &lt;span class="s2"&gt;"odd numbers in this array."&lt;/span&gt;
  &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Evens: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;evens&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
  &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Odds:  &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;odds&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;An array knows its size, so there is no need to keep track of it separately.&lt;/li&gt;
  &lt;li&gt;Ruby integers have handy &lt;code&gt;even?&lt;/code&gt; and &lt;code&gt;odd?&lt;/code&gt; methods that return true or false.
Under the hood, that method is doing exactly what you did: &lt;code&gt;n % 2 == 0&lt;/code&gt;.&lt;sup id="fnref:rb-parity"&gt;&lt;a href="#fn:rb-parity" class="footnote" rel="footnote" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt;
&lt;/li&gt;
  &lt;li&gt;Reducing &lt;code&gt;if&lt;/code&gt;/&lt;code&gt;else&lt;/code&gt; branches and loops helps the reader understand what is
happening.&lt;/li&gt;
  &lt;li&gt;Yours might have better performance, especially as input size approaches
infinity.&lt;/li&gt;
  &lt;li&gt;Your &lt;code&gt;print&lt;/code&gt; statements ending in &lt;code&gt;\n&lt;/code&gt; are fine, but you’ll more likely see
people using &lt;code&gt;puts&lt;/code&gt; with string interpolation (&lt;code&gt;#{}&lt;/code&gt;) when they want to print
a string ending in a new line.&lt;/li&gt;
  &lt;li&gt;In a real-world application, I would probably not put the screen output as
part of the computation logic. You’d probably want to return a hash or other
data structure and put the presentation logic somewhere else.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id="an-alternate-implementation"&gt;An Alternate Implementation&lt;/h2&gt;

&lt;p&gt;There is more than one way to skin a cat. Here’s an alternate implementation:&lt;/p&gt;

&lt;div class="language-ruby highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;parity_counts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ns&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;ns&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;([[],[]]){&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;odd?&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;n&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;n&lt;/span&gt;&lt;span class="p"&gt;;[&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="p"&gt;]}&lt;/span&gt;&lt;span class="sh"&gt;
end
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This will return an array where the first element is an array of even numbers,
and the second is an array of odd numbers. But there is very little about this
solution that is best practice. Clarity should be preferred to brevity:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Variable names should reflect what is stored in them. Single letter names and
even some abbreviations don’t make it immediately clear as to what it is to be
used for.&lt;/li&gt;
  &lt;li&gt;
&lt;code&gt;reduce&lt;/code&gt; is a concept that is not easy to grasp. I use it sparingly when it
really makes the most sense, rather than just because it makes me feel smart.&lt;/li&gt;
  &lt;li&gt;When you have more than one statement inside an iterator, it’s good style to
use &lt;code&gt;do&lt;/code&gt;/&lt;code&gt;end&lt;/code&gt; instead of curly braces, and break up the statement into multiple
lines. There are varying schools of thought on this:
    &lt;ul&gt;
      &lt;li&gt;
&lt;a href="http://www.virtuouscode.com/2011/07/26/the-procedurefunction-block-convention-in-ruby/"&gt;Some people&lt;/a&gt; use curly braces when they are using the value returned
from the iterator (e.g. give me the parent contact email for each student),
and &lt;code&gt;do&lt;/code&gt;/&lt;code&gt;end&lt;/code&gt; when they are mutating state (e.g. take this list of students
and calculate each one’s grade)&lt;/li&gt;
      &lt;li&gt;Other people say to always use curly braces for single line and use &lt;code&gt;do&lt;/code&gt;/&lt;code&gt;end&lt;/code&gt;
for multiple lines. I follow this pattern; I think it looks nicer.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id="a-better-version-of-the-alternate-implementation"&gt;A Better Version of the Alternate Implementation&lt;/h2&gt;

&lt;p&gt;So, given the concepts above, using &lt;code&gt;reduce&lt;/code&gt;, I would write it this way:&lt;/p&gt;

&lt;div class="language-ruby highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;parity_counts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;([[],&lt;/span&gt; &lt;span class="p"&gt;[]])&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;evens&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;odds&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
    &lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;odd?&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="n"&gt;odds&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;evens&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;evens&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;odds&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;[[], []]&lt;/code&gt; sets up the data structure that we are going to pass to the first
iteration to store the values in. Reduce takes the return value of the block and
passes as the first argument to the next iteration. By putting parens around
&lt;code&gt;(even, odd)&lt;/code&gt;, we can “unwrap” the array into separate arguments. It’s kind of a
confusing concept to wrap your mind around, but once you get it, it’s incredibly
handy for writing iterators.&lt;/p&gt;

&lt;h2 id="takeaways"&gt;Takeaways&lt;/h2&gt;

&lt;p&gt;In conclusion, a couple takeaways: First, Ruby has a huge standard library,
along with helper methods to do common things. It’s usually a good idea to check
out the documentation for a given class to see if there is already a method to
do what you’re trying to do (&lt;code&gt;even?&lt;/code&gt; and &lt;code&gt;odd?&lt;/code&gt; from above, for example).&lt;/p&gt;

&lt;p&gt;Second, with Ruby, it’s possible to write code that can almost be read as a
sentence. Variable names and function names following this pattern make your
code easier to understand and, in my opinion, much more fun to write.&lt;/p&gt;

&lt;h2 id="update-how-about-enumerablepartition"&gt;UPDATE: How about &lt;code&gt;Enumerable#partition?&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;There’s almost always a better way. Turns out, Ruby already has a method for
partitioning an enumerable. In this implementation, we ask each element in the
array if it is even. If so, it goes into the first partition. Otherwise, it
goes into the second.&lt;/p&gt;

&lt;div class="language-ruby highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="n"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;partition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="ss"&gt;:even?&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;#=&amp;gt; [[2, 4, 6], [1, 3, 5]]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This is the shorthand syntax (using &lt;a href="https://blog.pjam.me/posts/ruby-symbol-to-proc-the-short-version/"&gt;&lt;code&gt;Symbol#to_proc&lt;/code&gt;&lt;/a&gt;—a post for
another day, perhaps) that would be equivalent to writing&lt;/p&gt;

&lt;div class="language-ruby highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="n"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;partition&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;even?&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;So to put this back in to solve the original problem:&lt;/p&gt;

&lt;div class="language-ruby highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;parity_counts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;evens&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;odds&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;partition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="ss"&gt;:even?&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"There are &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;evens&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;size&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; even numbers and &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;odds&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;size&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
       &lt;span class="s2"&gt;"odd numbers in this array."&lt;/span&gt;
  &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Evens: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;evens&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
  &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Odds:  &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;odds&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class="footnotes" role="doc-endnotes"&gt;
  &lt;ol&gt;
    &lt;li id="fn:rb-parity"&gt;
      &lt;p&gt;The source for this function is in C, but &lt;a href="https://github.com/ruby/ruby/blob/74cdd893eb102ba98e735f2a24c710e1928261a9/numeric.c#L3173-L3188"&gt;here it is&lt;/a&gt; if you want to take a look at it. &lt;a href="#fnref:rb-parity" class="reversefootnote" role="doc-backlink"&gt;↩︎&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
&lt;img src="https://analytics.ptx.sh/p/SjOB3oKbb?id=QXV1IIX12N63QN9GZMMLVDAFPG&amp;url=%2Fnotes%2Fprogramming%2F2017%2F03%2F10%2Fadam-asks-parity-blocks-enumerators-oh-my%2F" alt="" /&gt;
    </content>
  </entry>
  
  <entry>
    <title>I Lost My Wedding Ring</title>
    <link href="https://ptx.sh/notes/life/2017/03/03/i-lost-my-wedding-ring-and-lived-to-tell-the-story/"/>
    <updated>2017-03-03T09:00:00-06:00</updated>
    <id>https://phillipridlen.com/notes/id/K34ENM9PYUSA9PCVT5SAL8SI4B</id>
    <content type="html">
      &lt;p&gt;I have a wedding ring in the Pacific Ocean somewhere.&lt;/p&gt;

&lt;p&gt;No, it wasn’t &lt;a href="https://www.youtube.com/watch?v=I51aM8cWUj8"&gt;some dramatic gesture&lt;/a&gt;. In fact, the story is not really
that interesting. We were in Puerto Vallarta for my brother’s wedding a few
years ago, and my wife and I decided to go for an evening swim. I left my
wedding ring on because I didn’t think it would fall off. It fell off. I never
found it.&lt;/p&gt;

&lt;p&gt;&lt;img src="pva-ocean-sunset.jpg" class="framed"&gt;&lt;/p&gt;

&lt;figcaption&gt;The little cove in the Pacific where my ring forever rests.&lt;/figcaption&gt;

&lt;p&gt;When I still had that original wedding ring, I was constantly afraid of losing
it or not knowing where it was. Losing the wedding ring was liberating, in a
way, because now I place more weight on the &lt;em&gt;meaning&lt;/em&gt; of the symbol on my finger
than the actual object itself.&lt;/p&gt;

&lt;p&gt;The modern practice of men wearing a wedding band only really dates back about a
hundred years, and mostly due to increased advertising from the jewelry
industry.&lt;/p&gt;

&lt;p&gt;All that aside, I wear the band for two main reasons. First, to remind myself
that I made a commitment to my wife. It’s heavy, almost 18 grams. I notice it
when it’s there, and I notice it when it’s not there. Whether or or off, I’m
reminded of my commitment. And second, to proclaim my undying and unconditional
love for my wife to the rest of the world.&lt;/p&gt;

&lt;p&gt;Divorce has never been an option, in my mind. I can’t imagine doing life without
her. I only have one ring that I’ve replaced the wedding band with, but if I had
to replace it again, it wouldn’t matter. Because it’s not the ring itself that’s
important, but the constant reminder of my commitment to her.&lt;/p&gt;
&lt;img src="https://analytics.ptx.sh/p/SjOB3oKbb?id=K34ENM9PYUSA9PCVT5SAL8SI4B&amp;url=%2Fnotes%2Flife%2F2017%2F03%2F03%2Fi-lost-my-wedding-ring-and-lived-to-tell-the-story%2F" alt="" /&gt;
    </content>
  </entry>
  
  <entry>
    <title>Programming as an Image-Bearer</title>
    <link href="https://ptx.sh/notes/christianity/2017/03/02/programming-as-an-image-bearer/"/>
    <updated>2017-03-02T09:00:00-06:00</updated>
    <id>https://phillipridlen.com/notes/id/050CM1AJGKLXT0WPOCDQD8UHWS</id>
    <content type="html">
      &lt;p&gt;Adam Murray, in an &lt;a href="https://www.thegospelcoalition.org/article/coding-for-the-kingdom"&gt;interview with The Gospel
Coalition&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;As an image-bearer of God, how does your work reflect some aspect of God’s work?&lt;/p&gt;

  &lt;p&gt;At the hackathon last year, a theology professor gave a talk where he described
coding as an extension of Genesis 1–2. First, there was nothing; then, God spoke
and made this awesome universe. Similarly, coding is turning ideas—essentially
nothing—into reality through computer language. It’s a cool reflection of the
image of God in humanity.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That you’re building something from basically nothing has long been my favorite
thing about programming. I’ve never thought about how it ties in with Genesis in
God’s act of creating the universe &lt;em&gt;ex nihilo&lt;/em&gt;. Every time we start a new
project or feature, we have the opportunity to bring glory to the First Creator.&lt;/p&gt;

&lt;img src="https://analytics.ptx.sh/p/SjOB3oKbb?id=050CM1AJGKLXT0WPOCDQD8UHWS&amp;url=%2Fnotes%2Fchristianity%2F2017%2F03%2F02%2Fprogramming-as-an-image-bearer%2F" alt="" /&gt;
    </content>
  </entry>
  
  <entry>
    <title>A Little "Special" Goes a Long Way</title>
    <link href="https://ptx.sh/notes/programming/2015/03/04/a-little-special-goes-a-long-way/"/>
    <updated>2015-03-04T09:00:00-06:00</updated>
    <id>https://phillipridlen.com/notes/id/UA31NPHE3PBZBEO0CXHE7ZWL1L</id>
    <content type="html">
      &lt;p&gt;&lt;em class="intro"&gt;
This post was originally published on the &lt;a href="https://web.archive.org/web/20150316123458/http://ovenbits.com/journal/your-success-is-our-success"&gt;Oven Bits Journal&lt;/a&gt;, under
the titles, “Your Success is Our Success”, and “Being Agile Leads to Results”.
It has been reproduced here for posterity.
&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Every client will tell you that they want two things: be on time, and stay
within their budget. At the heart of every project, every client also wants a
third thing–results. We like to take it one step further and say that every
client wants us to be on time, stay within their budget, deliver results, and be
special every step of the way.&lt;/p&gt;

&lt;p&gt;&lt;img src="desk.jpg" class="framed"&gt;&lt;/p&gt;

&lt;h2 id="discovering-results"&gt;Discovering Results&lt;/h2&gt;

&lt;p&gt;Before we even start work on a project, we ask, “why?” and dig deep. Why are we
building this? Why would someone use it? What is the desired result? We want to
learn what makes our clients and their customers tick. We outline key metrics
during this time that we’ll use later on to validate our assumptions. If we
don’t know how our clients define success for the project, we won’t know if
we’ve succeeded in meeting their expectations.&lt;/p&gt;

&lt;p&gt;Far too often, a project will set off on the wrong foot if the team doesn’t have
a clear vision. The tricky part of any engagement is knowing when to stand your
ground versus being flexible to what the client desires. The key is knowing how
to test and validate your assumptions. With a disciplined build, measure, learn
process you’ll be able to validate any assumptions that the team has developed.
Basing six-figure decisions on intuition and gut feel is just plain foolish. If
it can be measured and tested, it should be. As one of our clients so
brilliantly put it, “My opinion does not matter.” After we all had a good
chuckle, he was clear to reiterate, “No really, it doesn’t matter. All that
matters is what our consumers say.”&lt;/p&gt;

&lt;h2 id="beware-vanity-metrics"&gt;Beware: Vanity Metrics&lt;/h2&gt;

&lt;p&gt;Finding the right metrics to track is no simple task. Product development
teams—including ourselves—can easily get distracted by vanity metrics. These are
the big numbers that sound impressive and make you feel confident you are on the
right track. 100,000 downloads on the App Store. 20,000 signups. How do these
impressive and seemingly benign statistics secretly undermine what you are
trying to accomplish?&lt;/p&gt;

&lt;p&gt;In The Lean Startup, Eric Ries writes, “Vanity metrics can allow [you] to form
false conclusions and live in [your] own private reality.” Ultimately, vanity
metrics distract us from—or worse, blind us to—the results we’re trying to
achieve.&lt;/p&gt;

&lt;p&gt;What metrics point us toward the results our clients want? Ones that provide a
clear path for action. Sure, 100,000 downloads is great. But how long has your
app been available? How many of those who downloaded the app continue to use it
on a regular basis? Are people purchasing the in-app purchases? Do you know why?
We stay ahead of the game by asking these questions early and often.&lt;/p&gt;

&lt;p&gt;Instead of focusing on the vanity metrics, take a look at time in app, repeat
usage, and metrics that can’t be propped up from a massive, one-time advertising
spend. That’s when things will get real for you.&lt;/p&gt;

&lt;h2 id="a-dash-of-special-sauce"&gt;A Dash of Special Sauce&lt;/h2&gt;

&lt;p&gt;Being on time and on budget will get you a passing grade. Asking the right
questions and having the right answers will get you a B. In order to truly
succeed, we can’t simply meet expectations. We must exceed them. Chris Bowler
&lt;a href="http://chrisbowler.com/journal/defining-customer-success"&gt;hits the nail on the head&lt;/a&gt;: “Your goal as a business should be to make your
customer look as good as possible.”&lt;/p&gt;

&lt;p&gt;This can come in many forms. Often it’s something extra thrown in with a
deliverable, whether it’s a planned feature ready to go ahead of schedule or a
special interaction animation. &lt;a href="https://twitter.com/RetailProphet/status/571417876109905920"&gt;Sometimes it’s a batch of cookies&lt;/a&gt; or
cupcakes.  Sometimes it’s just a note of encouragement or gratitude written to
the client.&lt;/p&gt;

&lt;p&gt;Our success rides on the shoulders of the success of our clients and customers.
Only when we meet and exceed their expectations can we say we’ve done our job.&lt;/p&gt;

&lt;img src="https://analytics.ptx.sh/p/SjOB3oKbb?id=UA31NPHE3PBZBEO0CXHE7ZWL1L&amp;url=%2Fnotes%2Fprogramming%2F2015%2F03%2F04%2Fa-little-special-goes-a-long-way%2F" alt="" /&gt;
    </content>
  </entry>
  
  <entry>
    <title>On Being Friendly</title>
    <link href="https://ptx.sh/notes/life/2015/01/06/on-being-friendly/"/>
    <updated>2015-01-06T09:00:00-06:00</updated>
    <id>https://phillipridlen.com/notes/id/PLBY6AZ721A69DJO32MA26MAZ8</id>
    <content type="html">
      &lt;p&gt;John Saddington, on &lt;a href="https://web.archive.org/web/20201130045512/https://john.do/friendly/"&gt;his blog&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Friendly? Ah, that’s curious to me because I have not always been the nicest nor the friendliest
person on the internet. The truth is that I once saw the internet as an opportunity to just shout
my own opinion at people instead of seeing it as an opportunity to close the gap between myself
and many other individuals. . . . After being treated poorly myself I decided that I didn’t want
to do that to others.&lt;/p&gt;

  &lt;p&gt;So, I suppose, I became a much more friendlier netizen.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It never hurts to be a nice person. People will take notice. And, of course—as we all
know—&lt;a href="http://paulgraham.com/mean.html"&gt;&lt;em&gt;Mean People Fail&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt; Fixed the broken link to John’s blog which was previously on the &lt;a href="http://desk.pm"&gt;Desk&lt;/a&gt;
site.&lt;/p&gt;
&lt;img src="https://analytics.ptx.sh/p/SjOB3oKbb?id=PLBY6AZ721A69DJO32MA26MAZ8&amp;url=%2Fnotes%2Flife%2F2015%2F01%2F06%2Fon-being-friendly%2F" alt="" /&gt;
    </content>
  </entry>
  
  <entry>
    <title>Telegram Reaches 1 Billion Daily Messages</title>
    <link href="https://ptx.sh/notes/technology/2014/12/18/telegram-1-billion-daily-messages/"/>
    <updated>2014-12-18T09:00:00-06:00</updated>
    <id>https://phillipridlen.com/notes/id/VUZS4SIGY51UCV8SBFD3B36286</id>
    <content type="html">
      &lt;p&gt;Not sure how I missed the whole &lt;a href="http://www.theverge.com/2014/2/25/5445864/telegram-messenger-hottest-app-in-the-world"&gt;Telegram thing back in February&lt;/a&gt; when WhatsApp went
down. While nothing compared to WhatsApp’s 600 million active users, Telegram’s 50 million active
users each sending 20 messages a day with no money spent
on advertising is nothing to shake a stick at.&lt;/p&gt;

&lt;p&gt;What intrigues me the most is that it is set up as a &lt;a href="https://telegram.org/faq#q-how-are-you-going-to-make-money-out-of-this"&gt;non-commercial
organization&lt;/a&gt; promising to
never show ads or sell your data, along with the ability to send &lt;a href="https://telegram.org/faq#secret-chats"&gt;“secret
chats”&lt;/a&gt; with end-to-end encryption–only the two devices in
question can read the message.&lt;/p&gt;

&lt;p&gt;It’s a cool initiative; I’m curious how this all is going to shake out as Facebook continues to pour
more money into Messenger and WhatsApp and vie for market share.&lt;/p&gt;

&lt;p&gt;And please—feel free to &lt;a href="https://telegram.me/philtr"&gt;Telegram me&lt;/a&gt; any time.&lt;/p&gt;

&lt;img src="https://analytics.ptx.sh/p/SjOB3oKbb?id=VUZS4SIGY51UCV8SBFD3B36286&amp;url=%2Fnotes%2Ftechnology%2F2014%2F12%2F18%2Ftelegram-1-billion-daily-messages%2F" alt="" /&gt;
    </content>
  </entry>
  
  <entry>
    <title>Google Web Fonts Typographic Project</title>
    <link href="https://ptx.sh/notes/programming/2014/12/17/google-web-fonts-typographic-project/"/>
    <updated>2014-12-17T09:00:00-06:00</updated>
    <id>https://phillipridlen.com/notes/id/FNLWQLKPKNDMQB88891DAF0UZ2</id>
    <content type="html">
      &lt;blockquote&gt;
  &lt;p&gt;There are over 650 &lt;a href="https://www.google.com/fonts"&gt;Google Fonts&lt;/a&gt; available for free. But, pairing
typefaces isn’t easy and many of those fonts don’t work for typical websites. Part of the
&lt;a href="http://25x52.com/"&gt;25x52&lt;/a&gt; initiative, this collaborative, ongoing project offers inspiration for
using Google’s font library.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Passages from Æsop’s Fables set beautifully in web fonts available from &lt;a href="http://www.google.com/fonts"&gt;Google
fonts&lt;/a&gt;. There are some great choices available if you can find
them and use them properly.&lt;/p&gt;

&lt;img src="https://analytics.ptx.sh/p/SjOB3oKbb?id=FNLWQLKPKNDMQB88891DAF0UZ2&amp;url=%2Fnotes%2Fprogramming%2F2014%2F12%2F17%2Fgoogle-web-fonts-typographic-project%2F" alt="" /&gt;
    </content>
  </entry>
  
  <entry>
    <title>The curse of compressing reality</title>
    <link href="https://ptx.sh/notes/life/2014/12/16/the-curse-of-compressing-reality/"/>
    <updated>2014-12-16T09:00:00-06:00</updated>
    <id>https://phillipridlen.com/notes/id/8WNSP8QNLZ9RYH1JSDY4NZSL1V</id>
    <content type="html">
      &lt;p&gt;Noah Lorang on &lt;a href="https://signalvnoise.com/posts/3813-the-curse-of-compressing-reality"&gt;Signal v. Noise&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Any creative endeavor is highly non-linear, but the sharing of it almost always skips a lot of the
actual work that goes into it. That’s ok; a clear progression makes for a good story that’s easy
to tell. But don’t judge your reality against someone else’s compressed work. It’s ok if it takes
you a day to make a cutting board like one that someone made in six minutes on YouTube; the truth
is it probably took them a day too.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It’s easy to look at all the awesome stuff on the internet and get depressed that you can’t do
something well in a day or a weekend. Spending a couple hours doing parts of a project that are not
glamorous is OK and to be expected.&lt;/p&gt;

&lt;img src="https://analytics.ptx.sh/p/SjOB3oKbb?id=8WNSP8QNLZ9RYH1JSDY4NZSL1V&amp;url=%2Fnotes%2Flife%2F2014%2F12%2F16%2Fthe-curse-of-compressing-reality%2F" alt="" /&gt;
    </content>
  </entry>
  
  <entry>
    <title>O Come Let Us Adore Him</title>
    <link href="https://ptx.sh/notes/christianity/2014/12/13/o-come-let-us-adore-him/"/>
    <updated>2014-12-13T09:00:00-06:00</updated>
    <id>https://phillipridlen.com/notes/id/QWCPT92N0VXSBM9O9S0VWWMHC4</id>
    <content type="html">
      &lt;p&gt;&lt;a href="http://www.desiringgod.org/blog/posts/one-carol-three-marriages-o-come-all-ye-faithful"&gt;John Piper&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;And so the “us” of “O come let us adore him” is the “us” of heaven and earth, singing together.
According to Revelation 9:16, there are at least 200 million angels at God’s bidding. Surely at
least some of them are assigned to give heed to us as we sing, and do what we say: “Sing choirs of
angels, sing in exultation!” If we could only hear! Heaven and earth married in singing to Christ.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The choir of men and angels join together in song to worship the creator of the universe, who came
to rescue and restore the human race from our own brokenness.&lt;/p&gt;

&lt;p&gt;I love this dissection of such a beautiful and rich hymn. Christmas is about so much more than just
a cute little baby Jesus in the manger.&lt;/p&gt;

&lt;img src="https://analytics.ptx.sh/p/SjOB3oKbb?id=QWCPT92N0VXSBM9O9S0VWWMHC4&amp;url=%2Fnotes%2Fchristianity%2F2014%2F12%2F13%2Fo-come-let-us-adore-him%2F" alt="" /&gt;
    </content>
  </entry>
  
  <entry>
    <title>Being Careful About What We Ingest</title>
    <link href="https://ptx.sh/notes/christianity/2014/12/10/being-careful-about-what-we-ingest/"/>
    <updated>2014-12-10T09:00:00-06:00</updated>
    <id>https://phillipridlen.com/notes/id/N04FBYLC8KB4RDCO1E1J1KWMF2</id>
    <content type="html">
      &lt;p&gt;&lt;a href="http://www.esvbible.org/Romans+8:5-6/"&gt;Romans 8:5-6 (ESV)&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;For those who live according to the flesh set their minds on the things of the flesh, but those
who live according to the Spirit set their minds on the things of the Spirit. For to set the mind
on the flesh is death, but to set the mind on the Spirit is life and peace.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Many people are very careful about what they eat. We are careful to make sure we eat our fruits and
vegetables. We are careful about how much fat and how many carbohydrates we eat.  In the same way,
we should be careful about what we eat, but on a spiritual plane. With what kinds of things are we
saturating our minds? What kinds of junk food are we allowing into our homes and minds via
television, books, and the internet?&lt;/p&gt;

&lt;p&gt;Paul urges us in his letter to the Colossians to be mind&lt;em&gt;ful&lt;/em&gt; of our mind&lt;em&gt;set&lt;/em&gt;. “If
then you have been raised with Christ, … Set your minds on things that are above, not on things
that are on earth. For you have died, and your life is hidden with Christ in God.” &lt;sup id="fnref:fn-col-3-1-2"&gt;&lt;a href="#fn:fn-col-3-1-2" class="footnote" rel="footnote" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;Have we been raised with Christ? Yes! So what are we to do? Set our minds on the the things of God.
Not that we shouldn’t be concerned with day-to-day affairs, but that our &lt;em&gt;mindset&lt;/em&gt; would be one that
reflects God’s glory. I don’t want to make lists of movies, books, or websites that we can or can’t
watch, read, or visit. Our motive is not to increase morality. It is not to try to appease God’s
anger at our sin by saying “I don’t watch R-rated movies.” We don’t gain any favor with God by
keeping lists of rules. The Pharisees tried that and Jesus spoke most vehemently against their ways.
Our goal is to reflect to others the glory and grace of our Lord to those who have not seen or known
him.&lt;/p&gt;

&lt;p&gt;The only way to reflect God’s glory is to saturate our minds with the things that do.  “Finally,
brothers, whatever is true, … honorable, … just, … pure, …  lovely, … commendable,
[excellent, or praiseworthy], think about these things.” &lt;sup id="fnref:fn-phil-4-8"&gt;&lt;a href="#fn:fn-phil-4-8" class="footnote" rel="footnote" role="doc-noteref"&gt;2&lt;/a&gt;&lt;/sup&gt; Is that movie we want to go
see really excellent and praiseworthy? How about that latest bestseller we see on the shelves at the
bookstore? Is it pure and lovely? The blogs we like to read—are they true and honorable or do
they defame others with lies? We shouldn’t shelter ourselves from these things, &lt;sup id="fnref:fn-1cor-5-9-13"&gt;&lt;a href="#fn:fn-1cor-5-9-13" class="footnote" rel="footnote" role="doc-noteref"&gt;3&lt;/a&gt;&lt;/sup&gt;
but we should always be on our guard.&lt;/p&gt;

&lt;div class="footnotes" role="doc-endnotes"&gt;
  &lt;ol&gt;
    &lt;li id="fn:fn-col-3-1-2"&gt;
      &lt;p&gt;&lt;a href="http://www.esvbible.org/Colossians+3:1-2/"&gt;Colossians 3:1-2, ESV.&lt;/a&gt; &lt;a href="#fnref:fn-col-3-1-2" class="reversefootnote" role="doc-backlink"&gt;↩︎&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id="fn:fn-phil-4-8"&gt;
      &lt;p&gt;&lt;a href="http://www.esvbible.org/Philippians+4:8/"&gt;Philippians 4:8, ESV&lt;/a&gt; &lt;a href="#fnref:fn-phil-4-8" class="reversefootnote" role="doc-backlink"&gt;↩︎&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id="fn:fn-1cor-5-9-13"&gt;
      &lt;p&gt;&lt;em&gt;cf.&lt;/em&gt; &lt;a href="http://www.esvbible.org/1Corinthians+5:9-13/"&gt;1 Corinthians 5:9-13&lt;/a&gt; &lt;a href="#fnref:fn-1cor-5-9-13" class="reversefootnote" role="doc-backlink"&gt;↩︎&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
&lt;img src="https://analytics.ptx.sh/p/SjOB3oKbb?id=N04FBYLC8KB4RDCO1E1J1KWMF2&amp;url=%2Fnotes%2Fchristianity%2F2014%2F12%2F10%2Fbeing-careful-about-what-we-ingest%2F" alt="" /&gt;
    </content>
  </entry>
  
  <entry>
    <title>Jekyll, S3, and CloudFront</title>
    <link href="https://ptx.sh/notes/programming/2014/12/06/jekyll-s3-cloudfront/"/>
    <updated>2014-12-06T09:00:00-06:00</updated>
    <id>https://phillipridlen.com/notes/id/X0WMM2TPMESFNOK4I9BJWH896K</id>
    <content type="html">
      &lt;p&gt;GitHub pages is awesome. Like, &lt;em&gt;really&lt;/em&gt; awesome. But I wanted to try something new that would give
me a little more flexibility (e.g. the ability to use Jekyll plugins). So I started looking around
for the best way to deploy my static site to S3.&lt;/p&gt;

&lt;p&gt;Boy, did I ever tumble down a rabbit hole. It seems like everyone’s got their own idea of &lt;a href="http://vvv.tobiassjosten.net/development/jekyll-blog-on-amazon-s3-and-cloudfront/"&gt;how
it&lt;/a&gt; &lt;a href="http://brettterpstra.com/2014/02/21/a-jekyll-cdn-with-cloudfront/"&gt;should
work&lt;/a&gt;, each with their custom
one-off scripts that I would hate to debug, and not fully supporting what I was trying to
accomplish. That’s when I remembered seeing &lt;a href="https://github.com/laurilehmijoki/jekyll-s3"&gt;jekyll-s3&lt;/a&gt;
at some point in history, so I thought I would at least check it out to see if development was still
active. Well, as it turns out, development has indeed continued, just on a different project called
&lt;a href="https://github.com/laurilehmijoki/s3_website"&gt;s3_website&lt;/a&gt;. &lt;code&gt;s3_website&lt;/code&gt; can deploy any set of files
to Amazon S3, but Jekyll and Nanoc are supported right out of the box with no additional
configuration.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;s3_website&lt;/code&gt; is a mature and powerful tool. Not only does it deploy your site to S3, but it has a
host of other features. If you set up CloudFront to distribute your website from S3, &lt;code&gt;s3_website&lt;/code&gt;
will handle all the cache invalidation commands so you don’t have to worry about it. It also
supports &lt;a href="https://github.com/bkeepers/dotenv"&gt;dotenv&lt;/a&gt; out of the box, so you can commit your
configuration file without sensitive access keys.&lt;/p&gt;

&lt;p&gt;The only downside is now I have to be at my computer to make a change to my website, but let’s be
honest here—how often is that situation going to come up? Considering my last post was written
nearly two years ago, not often.&lt;/p&gt;

&lt;img src="https://analytics.ptx.sh/p/SjOB3oKbb?id=X0WMM2TPMESFNOK4I9BJWH896K&amp;url=%2Fnotes%2Fprogramming%2F2014%2F12%2F06%2Fjekyll-s3-cloudfront%2F" alt="" /&gt;
    </content>
  </entry>
  
  <entry>
    <title>Returning Multiple Formats with Rails Dynamic Error Pages</title>
    <link href="https://ptx.sh/notes/programming/2012/12/13/returning-multiple-formats-with-custom-dynamic-error-pages-in-rails/"/>
    <updated>2012-12-13T09:00:00-06:00</updated>
    <id>https://phillipridlen.com/notes/id/G7RFUJQP1HTA1UFTHKIUQMV23M</id>
    <content type="html">
      &lt;p&gt;Yesterday my coworker &lt;a href="http://erichurst.com"&gt;Eric&lt;/a&gt; asked me to build out some dynamic error pages for the upcoming
version of one of our apps. He suggested a certain pattern that we used in a previous application.
Being the adventurous soul that I am, I wanted to make sure his way was the &lt;em&gt;best&lt;/em&gt; way. After some
deep &lt;s&gt;soul&lt;/s&gt; google searching, I found out that Eric’s method was considered best practice. It’s
described in some detail on &lt;a href="http://blog.plataformatec.com.br/2012/01/my-five-favorite-hidden-features-in-rails-3-2/"&gt;José Valim’s blog post&lt;/a&gt;, but I’ll break
it down for you here:&lt;/p&gt;

&lt;p&gt;First, we need a controller for our error pages. Start out with something simple, like this:&lt;/p&gt;

&lt;div class="language-ruby highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="c1"&gt;# app/controllers/errors_controller.rb&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ErrorsController&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationController&lt;/span&gt;
  &lt;span class="n"&gt;layout&lt;/span&gt; &lt;span class="s1"&gt;'error'&lt;/span&gt; &lt;span class="c1"&gt;# only if you want a separate layout for your errors&lt;/span&gt;

  &lt;span class="c1"&gt;# 404 Not Found&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;not_found&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="c1"&gt;# 422 Unprocessable Entity&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;unprocessable&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="c1"&gt;# 500 Internal Server Error&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;internal_server&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now let’s add some routes:&lt;/p&gt;

&lt;div class="language-ruby highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="no"&gt;YourApp&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Application&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;routes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;draw&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;match&lt;/span&gt; &lt;span class="s1"&gt;'/404'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;to: &lt;/span&gt;&lt;span class="s1"&gt;'errors#not_found'&lt;/span&gt;
  &lt;span class="n"&gt;match&lt;/span&gt; &lt;span class="s1"&gt;'/422'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;to: &lt;/span&gt;&lt;span class="s1"&gt;'errors#unprocessable'&lt;/span&gt;
  &lt;span class="n"&gt;match&lt;/span&gt; &lt;span class="s1"&gt;'/500'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;to: &lt;/span&gt;&lt;span class="s1"&gt;'errors#internal_server'&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;With Rails 3.2, error pages have been extracted to a &lt;a href="http://stackoverflow.com/a/2257031/383950"&gt;Rack Middleware&lt;/a&gt;.  Fortunately for us, so
are the application routes. We can to tell rails to use our routes app for the error pages in
&lt;code&gt;config/application.rb&lt;/code&gt;:&lt;/p&gt;

&lt;div class="language-ruby highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="c1"&gt;# config/application.rb&lt;/span&gt;
&lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;YourApp&lt;/span&gt;
  &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Application&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;Rails&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Application&lt;/span&gt;
    &lt;span class="c1"&gt;# ...&lt;/span&gt;

    &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exceptions_app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;routes&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And that’s it! Add some page templates in &lt;code&gt;app/views/errors/&lt;/code&gt; and you should be good to go.&lt;/p&gt;

&lt;p&gt;To test it, we need to turn off the development mode error pages. Set &lt;code&gt;consider_all_requests_local&lt;/code&gt;
to false in &lt;code&gt;config/environments/development.rb&lt;/code&gt;:&lt;/p&gt;

&lt;div class="language-ruby highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="c1"&gt;# config/environments/development.rb&lt;/span&gt;
&lt;span class="no"&gt;YourApp&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Application&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;configure&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="c1"&gt;# ...&lt;/span&gt;

  &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;consider_all_requests_local&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kp"&gt;false&lt;/span&gt;

  &lt;span class="c1"&gt;# ...&lt;/span&gt;
 &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You’ll want to set that back to true before committing your code, or else you won’t receive any
helpful feedback while developing your application.&lt;/p&gt;

&lt;p&gt;All of the above steps were fairly simple, but figuring out how to determine which format to return
is a little complex.  &lt;code&gt;env['REQUEST_PATH']&lt;/code&gt; contains the error path (e.g. “/404”) and no format
information is getting passed to the errors controller, so the standard Rails &lt;code&gt;respond_to&lt;/code&gt; stuff is
not going to work here. We can grab the original request path via &lt;code&gt;env['ORIGINAL_FULLPATH']&lt;/code&gt;. I
added a few private methods to errors controller to help out. The first two help me figure out what
format the request came as. I want to return a JSON response if the request starts with ‘/api’ or
ends in ‘.json’. The third will render our template in the format we want.&lt;/p&gt;

&lt;div class="language-ruby highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ErrorsController&lt;/span&gt;
  &lt;span class="kp"&gt;private&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;api_request?&lt;/span&gt;
    &lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'ORIGINAL_FULLPATH'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=~&lt;/span&gt; &lt;span class="sr"&gt;/^\/api/&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;json_request?&lt;/span&gt;
    &lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'ORIGINAL_FULLPATH'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=~&lt;/span&gt; &lt;span class="sr"&gt;/\.json$/&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;render_error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;api_request?&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;json_request?&lt;/span&gt;
      &lt;span class="n"&gt;render&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.json.jbuilder"&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;
      &lt;span class="n"&gt;render&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.html.haml"&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now we just need to update the actions in our controller:&lt;/p&gt;

&lt;div class="language-ruby highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ErrorsController&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;not_found&lt;/span&gt;
    &lt;span class="n"&gt;render_error&lt;/span&gt; &lt;span class="s2"&gt;"not_found"&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;unprocessable&lt;/span&gt;
    &lt;span class="n"&gt;render_error&lt;/span&gt; &lt;span class="s2"&gt;"unprocessable"&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;internal_server&lt;/span&gt;
    &lt;span class="n"&gt;render_error&lt;/span&gt; &lt;span class="s2"&gt;"internal_server"&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And we’re done! Make sure you add your json templates to &lt;code&gt;app/views/errors&lt;/code&gt;.&lt;/p&gt;

&lt;div class="language-bash highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;curl http://localhost:3000/api/v1/nothing-here
&lt;span class="o"&gt;{&lt;/span&gt; error: &lt;span class="s2"&gt;"not_found"&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;curl http://localhost:3000/nothing-here.json
&lt;span class="o"&gt;{&lt;/span&gt; error: &lt;span class="s2"&gt;"not_found"&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;curl http://localhost:3000/nothing-here
&amp;lt;h1&amp;gt;404 Not Found&amp;lt;/h1&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;img src="https://analytics.ptx.sh/p/SjOB3oKbb?id=G7RFUJQP1HTA1UFTHKIUQMV23M&amp;url=%2Fnotes%2Fprogramming%2F2012%2F12%2F13%2Freturning-multiple-formats-with-custom-dynamic-error-pages-in-rails%2F" alt="" /&gt;
    </content>
  </entry>
  
  <entry>
    <title>Thank you, Dvorak!</title>
    <link href="https://ptx.sh/notes/programming/2011/11/11/thank-you-dvorak/"/>
    <updated>2011-11-11T09:00:00-06:00</updated>
    <id>https://phillipridlen.com/notes/id/V532ESFVEYJ56K8LUEDCBQKHRG</id>
    <content type="html">
      &lt;p&gt;&lt;em&gt;Dvorak&lt;/em&gt;. Not exactly a common name.&lt;/p&gt;

&lt;p&gt;There are a few famous folks with that name. Antonín Dvořák composed the New World Symphony during a
visit to the United States in 1893 (but I can’t hum a single theme from it). There’s also Dusty
Dvorak, a gold-medal-winning U.S. volleyball player in the 1984 Summer Olympics (I wasn’t born yet).
Some people might think of Ann Dvorak, the American actress from the early 20th century (I haven’t
seen any of her movies). If you’re into technology like I am, you probably have seen John C.
Dvorak’s columns in &lt;em&gt;PC Magazine&lt;/em&gt; or &lt;em&gt;InfoWorld&lt;/em&gt; (I tend to disagree with his opinions).&lt;/p&gt;

&lt;p&gt;The Dvorak that I am most thankful for is August Dvorak, the educational psychologist and professor
at the University of Wisconsin. You probably haven’t heard much about him. He and his
brother-in-law, William Dealey, created the &lt;a href="http://en.wikipedia.org/wiki/Dvorak_Simplified_Keyboard%20[wp]:%20http://wordpress.org/"&gt;Dvorak Simplified Keyboard&lt;/a&gt; layout. What’s the
Dvorak Simplified Keyboard layout, you ask? I’ll tell you. But first, a quick history lesson:&lt;/p&gt;

&lt;p&gt;It was the late 1860s. Christopher Sholes, Carlos Glidden, and Samuel W. Soule were designing and
building the first commercially-successful typewriter, the Remington No. 1. As they were building
it, they noticed that when two keys near each other were pressed in rapid succession, the typewriter
had a tendency to jam due to the mechanical levers that would swing up to print the letter on the
page. This was a problem. They couldn’t just tell people to be more careful, so they decided to
rearrange the keys so that there would be fewer jams. The keys were spread out so that common letter
sequences would not be near each other. The typist could then press these two keys more rapidly with
fewer jams. This was the birth of the QWERTY layout. Despite initial criticisms, typewriters were a
huge success.&lt;/p&gt;

&lt;p&gt;Back to our friend August who, while advising a student’s master’s thesis on typing errors, became
interested in the subject. By the 1930s, typewriters were much more advanced, and their propensity
to jam had been greatly reduced. He and his brother-in-law meticulously studied every aspect of
typing, from the physiology of the hand to the most commonly used letters and letter sequences in
the English language. The end result: a keyboard layout that was able to to be learned, on average,
in one-third of the time that it took a typist to learn QWERTY, and consistently produced faster
typists who made fewer errors.&lt;/p&gt;

&lt;p&gt;&lt;img src="https://upload.wikimedia.org/wikipedia/commons/thumb/2/25/KB_United_States_Dvorak.svg/900px-KB_United_States_Dvorak.svg.png" alt=""&gt;&lt;/p&gt;

&lt;figcaption&gt;
  The US Dvorak keyboard layout.
  (Image: &lt;a href="https://en.wikipedia.org/wiki/Dvorak_Simplified_Keyboard"&gt;Wikipedia&lt;/a&gt;).
&lt;/figcaption&gt;

&lt;p&gt;The effort and attention to detail on the design of this layout is insane:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;70% of all keystrokes are on the home row (vs. 32% for QWERTY)&lt;/li&gt;
  &lt;li&gt;Most words will alternate back and forth nicely between your hands, because all vowels are typed
with your left hand.&lt;/li&gt;
  &lt;li&gt;The least common characters are placed on the bottom row&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Fast-forward to the digital age. We still type on keyboards, and we are no longer bound by the lever
action required to put characters on the page, yet we are still using a keyboard layout that was
designed for typewriter efficiency, not typist efficiency. Barbara Blackburn, the world’s fastest
typist, uses the Dvorak layout. Other proponents include Steve Wozniak of Apple fame and Matt
Mullenweg, creator of &lt;a href="http://wordpress.org"&gt;WordPress&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Before the Dvorak Simplified Keyboard layout, I was unable to teach myself to touch type. Forever
bound to my lovingly-named “3-finger claw” stance, I would type three letters, then backspace two,
type three letters, backspace two, and so on. By the time I finished a paragraph, my whole arm hurt.
Then Dvorak found me. I was forever changed. A fresh start. Within a month I was back up to my
original typing speed of 35 WPM. Within a year I doubled that. Thanks, Dvorak! (Take that, QWERTY!)&lt;/p&gt;

&lt;img src="https://analytics.ptx.sh/p/SjOB3oKbb?id=V532ESFVEYJ56K8LUEDCBQKHRG&amp;url=%2Fnotes%2Fprogramming%2F2011%2F11%2F11%2Fthank-you-dvorak%2F" alt="" /&gt;
    </content>
  </entry>
  
  <entry>
    <title>Less.app</title>
    <link href="https://ptx.sh/notes/programming/2011/05/04/less-dot-app/"/>
    <updated>2011-05-04T09:00:00-06:00</updated>
    <id>https://phillipridlen.com/notes/id/3P051GGW7A2BCPS6L817O9F2MG</id>
    <content type="html">
      &lt;p&gt;&lt;a href="http://incident57.com/less/"&gt;Less.app&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;{Less} extends CSS with variables, nested rules, operators and
more. If you’re still building websites without it, you’re an
idiot. This app makes it dead simple to use {Less} by automatically
compiling &lt;code&gt;*.less&lt;/code&gt; files into standard CSS.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;s&gt;Using it to precompile the styles for this very site.&lt;/s&gt;
&lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt; NOPE.&lt;/p&gt;

&lt;img src="https://analytics.ptx.sh/p/SjOB3oKbb?id=3P051GGW7A2BCPS6L817O9F2MG&amp;url=%2Fnotes%2Fprogramming%2F2011%2F05%2F04%2Fless-dot-app%2F" alt="" /&gt;
    </content>
  </entry>
  
  <entry>
    <title>Mom&amp;rsquo;s Secret Sauce for Success</title>
    <link href="https://ptx.sh/notes/life/2011/05/03/moms-secret-sauce-for-success/"/>
    <updated>2011-05-03T09:00:00-06:00</updated>
    <id>https://phillipridlen.com/notes/id/AWHTFCCF21WRZ5XQKO7OA6JNY2</id>
    <content type="html">
      &lt;p&gt;I owe every accomplishment I have ever achieved to three things my mom
instilled in me from a young age. She was relentless, frustrating at
times, but looking back I know it was out of a deep love for me and my
future well-being.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Always do your best&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Most of the time my grades were good. But I never got in trouble for bad
grades, unless they were a result of not trying. Every time I brought
home a paper with a bad grade, she’d ask me, “Could you have gotten a
better grade?” Most of the time, the answer was yes and I knew I had
been lazy. If I really had done my best, my mom praised me for the
effort I put in, and encouraged me to prepare for next time. As long as
I did my best, she was satisfied.&lt;/p&gt;

&lt;p&gt;Now, in my professional life, a job isn’t done until I’ve done my best.
Even when something appears to be done, I dig in and &lt;em&gt;refine, refine,
refine&lt;/em&gt; until I can honestly say I’ve done my best work.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Never be satisfied with the status quo&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I was a rockstar speller when I was in grade school. I’d look at a word,
write it out once or twice, and then it would be in my head forever (or
at least until the next spelling test). My mom caught on to my
abilities, and wouldn’t let me stop at the lists of 5-letter words my
teachers gave me.&lt;/p&gt;

&lt;p&gt;To this day, I try to push myself into uncomfortable territory. The only
way to better yourself is to step outside your comfort zone, and now I
have twenty-some years of practice thanks to my mom.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Be a life-long learner&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Our family vacations were primarily about spending time together, but
they were always educational. We wouldn’t just stop and look at the
sights to see, we would read every sign and soak up all the information
we could get. Even our destinations were educational. I learned all
about &lt;a href="http://www.desertmuseum.org/"&gt;wildlife&lt;/a&gt;,
&lt;a href="http://www.nps.gov/cave"&gt;caves&lt;/a&gt;, &lt;a href="http://www.titanmissilemuseum.org/"&gt;the Cold
War&lt;/a&gt;, and &lt;a href="http://www.b2science.org/"&gt;cutting-edge scientific
research&lt;/a&gt; on our vacations.&lt;/p&gt;

&lt;p&gt;Every once in a while, when I feel like I’m just drifting through life,
I’ll go learn something new and it gives me just the pick-me-up I need.&lt;/p&gt;

&lt;p&gt;Thanks, mom, for always encouraging to do my best, to not be satisfied
with the status quo, and to be a life-long learner. &lt;strong&gt;Happy mother’s
day!&lt;/strong&gt;&lt;/p&gt;
&lt;img src="https://analytics.ptx.sh/p/SjOB3oKbb?id=AWHTFCCF21WRZ5XQKO7OA6JNY2&amp;url=%2Fnotes%2Flife%2F2011%2F05%2F03%2Fmoms-secret-sauce-for-success%2F" alt="" /&gt;
    </content>
  </entry>
  
  <entry>
    <title>Gumbo</title>
    <link href="https://ptx.sh/notes/food/2011/04/30/gumbo/"/>
    <updated>2011-04-30T09:00:00-06:00</updated>
    <id>https://phillipridlen.com/notes/id/1FW3NY53MCAB46LUIJIECUR4LC</id>
    <content type="html">
      &lt;p&gt;My wife and I made &lt;a href="http://www.food.com/recipe/quick-n-easy-gumbo-89981"&gt;“Quick &amp;amp; Easy Gumbo”&lt;/a&gt; for an event at our church
this evening. I know it’s not “real” gumbo, but let me tell ya, it’s pretty
tasty.&lt;/p&gt;

&lt;p&gt;We modified the recipe in a couple ways, and learned a couple things in the
process about how we should have adjusted for those changes.&lt;/p&gt;

&lt;p&gt;First, we used hot breakfast sausage. The flavor on this stuff is amazing, but I
think it must have been a little leaner than the sausage the recipe was
expecting. I would recommend adding a tablespoon of oil to the your pan before
putting the sausage in so you don’t burn it.&lt;/p&gt;

&lt;p&gt;Second, and I suppose this applies to recipes in general, chop up everything
ahead of time because you won’t be able to stir continuously and chop up all
your veggies at the same time–at least not in 5 minutes.&lt;/p&gt;

&lt;p&gt;Third, I added about twice as much creole seasoning as the recipe called for. I
tend to like my food salty and spicy, so the recipe might suit your taste, but I
would suggest 1½ times the amount listed in the recipe.&lt;/p&gt;

&lt;p&gt;My cooking adventures will continue!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;UPDATE:&lt;/strong&gt; Louisiana lady says, “Good job on the Gumbo!” I’d say that’s a
success :)&lt;/p&gt;

&lt;img src="https://analytics.ptx.sh/p/SjOB3oKbb?id=1FW3NY53MCAB46LUIJIECUR4LC&amp;url=%2Fnotes%2Ffood%2F2011%2F04%2F30%2Fgumbo%2F" alt="" /&gt;
    </content>
  </entry>
  
  <entry>
    <title>Head in the Clouds</title>
    <link href="https://ptx.sh/notes/programming/2011/02/17/head-in-the-clouds/"/>
    <updated>2011-02-17T09:00:00-06:00</updated>
    <id>https://phillipridlen.com/notes/id/WRH4MV9ALKGTTFDKYS3EB6CV4G</id>
    <content type="html">
      &lt;p&gt;Valentine’s day was a few days ago, and since I’m still in the mood, I am going
to declare my love for the cloud. I love that at &lt;a href="http://balcomagency.com"&gt;Balcom
Agency&lt;/a&gt;, we host all of our websites in the cloud. What
advantage does this have, both for us as developers and for our clients?&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
&lt;strong&gt;Backups&lt;/strong&gt; – Nothing eases the mind of a web developer more than knowing
there are recent backups available in case of a disaster. Our hosting providers
make scheduling automatic backups dead simple.&lt;/li&gt;
  &lt;li&gt;
&lt;strong&gt;Launching a website&lt;/strong&gt; – I love launching a website into the cloud. Instead
of ordering a dedicated server from a hosting company that takes a couple days
to be built, I can, with a few clicks, create a new virtual server with just the
specs I need to run the website.&lt;/li&gt;
  &lt;li&gt;
&lt;strong&gt;Server replication&lt;/strong&gt; – When we need to make a change to a website,
sometimes we don’t want to mess with the version that’s currently running live.
I can create an exact duplicate server in a matter of minutes, and deploy the
updates to that server. The client can see and approve the changes without
running the risk of having unwanted side effects on the live website. This takes
a lot of stress off us as developers, because, believe it or not, we can make
mistakes too. We can do as many test runs as we need until we feel comfortable
and confident that we’ll make the changes swiftly and professionally.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The cloud is not the solution for every problem (as &lt;a href="http://youtu.be/mjtqoQE_ezA"&gt;Microsoft has
suggested&lt;/a&gt;), but we sure get a lot more done around
here because of it.&lt;/p&gt;
&lt;img src="https://analytics.ptx.sh/p/SjOB3oKbb?id=WRH4MV9ALKGTTFDKYS3EB6CV4G&amp;url=%2Fnotes%2Fprogramming%2F2011%2F02%2F17%2Fhead-in-the-clouds%2F" alt="" /&gt;
    </content>
  </entry>
  
  <entry>
    <title>Using the Heroku Gem Inside Your App</title>
    <link href="https://ptx.sh/notes/programming/2010/08/12/using-the-heroku-gem-inside-your-app/"/>
    <updated>2010-08-12T09:00:00-06:00</updated>
    <id>https://phillipridlen.com/notes/id/R34DWDS8XQQ6CQ2BM9GDQA0SS8</id>
    <content type="html">
      &lt;p&gt;Brett asked &lt;a href="http://groups.google.com/group/heroku/t/1b012e631dd80e64"&gt;this question&lt;/a&gt; on the Heroku mailing list:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;I want to let users purchase custom domain names to access my app on
  Heroku. When the purchase transaction takes place, I’d like to add the
  custom domain to my app in real time. I thought of using the Heroku
  gem/command line tool from within the app, analogous to the
  command-line expression: &lt;code&gt;heroku domains:add www.example.com&lt;/code&gt;. Is this
  possible?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It really got me thinking about exploring all that the Heroku API has to
offer.&lt;/p&gt;

&lt;p&gt;I thought I remembered seeing someone using the Heroku gem inside their
code before, but I couldn’t remember where, and I couldn’t seem to find
any examples in the &lt;a href="http://docs.heroku.com"&gt;Heroku docs&lt;/a&gt;. Good! Time to get my hands
dirty with some raw source code.&lt;/p&gt;

&lt;p&gt;I opened up the &lt;a href="https://github.com/heroku/legacy-cli/blob/888266abc63521782648f6522d0f7d7a062c67c8/lib/heroku/client.rb"&gt;Heroku client source code&lt;/a&gt; and it’s actually
designed to be used inside your code. How about that. The first few
lines after all the requires describe perfectly how to use it:&lt;/p&gt;

&lt;div class="language-ruby highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="c1"&gt;# A Ruby class to call the Heroku REST API.  You might use this if you want to&lt;/span&gt;
&lt;span class="c1"&gt;# manage your Heroku apps from within a Ruby program, such as Capistrano.&lt;/span&gt;
&lt;span class="c1"&gt;#&lt;/span&gt;
&lt;span class="c1"&gt;# Example:&lt;/span&gt;
&lt;span class="c1"&gt;#&lt;/span&gt;
&lt;span class="c1"&gt;#   require 'heroku'&lt;/span&gt;
&lt;span class="c1"&gt;#   heroku = Heroku::Client.new('me@example.com', 'mypass')&lt;/span&gt;
&lt;span class="c1"&gt;#   heroku.create('myapp')&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;As you scroll down through the functions, you find that you can do anything in
your source code that you could do on the command line. To answer the original
question, if you wanted to use this command-line task:&lt;/p&gt;

&lt;div class="language-sh highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;heroku domains:add www.example.com
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You would simply put these lines in your source code:&lt;/p&gt;

&lt;div class="language-ruby highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'heroku'&lt;/span&gt;
&lt;span class="n"&gt;heroku&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Heroku&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'me@example.com'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s1"&gt;'mypass'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;heroku&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_domain&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'myapp'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s1"&gt;'www.example.com'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The add_domain function is found on &lt;a href="https://github.com/heroku/legacy-cli/blob/888266abc63521782648f6522d0f7d7a062c67c8/lib/heroku/client.rb#L120-L122"&gt;line #120 of client.rb&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;UPDATE:&lt;/strong&gt; Someone replied to the thread, pointing out that you should
keep things such as your Heroku credentials out of your code and in an
environment variable. Heroku already stores your app name by default in
&lt;code&gt;ENV["APP_NAME"]&lt;/code&gt;. So, to make the above code a little DRYer and safe to
distribute. At the terminal:&lt;/p&gt;

&lt;div class="language-sh highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;heroku config:add &lt;span class="nv"&gt;HEROKU_EMAIL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;me@example.com &lt;span class="nv"&gt;HEROKU_PASS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;mypass
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And then in our code:&lt;/p&gt;

&lt;div class="language-ruby highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'heroku'&lt;/span&gt;
&lt;span class="n"&gt;heroku&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Heroku&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;ENV&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"HEROKU_EMAIL"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="no"&gt;ENV&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"HEROKU_PASS"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="n"&gt;heroku&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_domain&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;ENV&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"APP_NAME"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="s1"&gt;'www.example.com'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now we won’t be distributing our Heroku credentials with our code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;UPDATE #2:&lt;/strong&gt; Someone asked me if storing Heroku credentials as config
variables would be secure. &lt;a href="http://twitter.com/benhartney"&gt;Ben
Hartney&lt;/a&gt; had the same question and contacted Heroku support. Here is
their response:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Storing this information in an environment variable is safe. We also
  store your database connection info in environment variables, so we
  consider it secure.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;img src="https://analytics.ptx.sh/p/SjOB3oKbb?id=R34DWDS8XQQ6CQ2BM9GDQA0SS8&amp;url=%2Fnotes%2Fprogramming%2F2010%2F08%2F12%2Fusing-the-heroku-gem-inside-your-app%2F" alt="" /&gt;
    </content>
  </entry>
  
  <entry>
    <title>Shapeshifting &amp;ldquo;Classes&amp;rdquo;</title>
    <link href="https://ptx.sh/notes/programming/2010/08/05/shapeshifting-classes/"/>
    <updated>2010-08-05T09:00:00-06:00</updated>
    <id>https://phillipridlen.com/notes/id/2CD3G94GKEC5DN0EV6PBQXQEBV</id>
    <content type="html">
      &lt;p&gt;I’ve been using Ruby full-time+ for the last few weeks, working on projects at
work and then personal projects when I get home. There are a few things I’ve
learned about Ruby that surprised me. Most of these were discovered when, going
out on a limb, I tried something completely random to see if it worked–and it
did!&lt;/p&gt;

&lt;p&gt;On one of my projects, when initializing the application,  I needed to be able
to choose one class (we’ll call it &lt;code&gt;FujiApple&lt;/code&gt;) if certain variable was set, and a different
class (call it &lt;code&gt;Gala&lt;/code&gt;) if it was not. So I tried the following:&lt;/p&gt;

&lt;div class="language-ruby highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vi"&gt;@certain_var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;nil?&lt;/span&gt;
  &lt;span class="no"&gt;AppleType&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;GalaApple&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt;
  &lt;span class="no"&gt;AppleType&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;FujiApple&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now, keep in mind, &lt;code&gt;AppleType&lt;/code&gt; is not a class that I have defined anywhere in my
code, yet I could use it just the same as the class that I set it to!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What’s really going on here?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It took me a while to realize that I’m not actually creating a new class here
(and hence the reason I put “classes” in quotes). What’s actually happening
is that &lt;code&gt;AppleType&lt;/code&gt; is just a plain old constant. However, because that constant
is pointing to a class, you can use the same as if its own class.&lt;/p&gt;

&lt;p&gt;If my &lt;code&gt;FujiApple&lt;/code&gt; class looks like this:&lt;/p&gt;

&lt;div class="language-ruby highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;FujiApple&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;eat&lt;/span&gt;
    &lt;span class="s2"&gt;"NOM NOM NOM"&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;I can do this:&lt;/p&gt;

&lt;div class="language-ruby highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;AppleType&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;FujiApple&lt;/span&gt;
  &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;FujiApple&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;myApple&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;AppleType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;
  &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="c1"&gt;#&amp;lt;FujiApple:0x1011b31c0&amp;gt;&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;myApple&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;eat&lt;/span&gt;
  &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"NOM NOM NOM"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Should I use it?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I’m not &lt;em&gt;quite&lt;/em&gt; sure how good this practice actually is, because if we need to
change the &lt;code&gt;AppleType&lt;/code&gt; somewhere in the middle of the application run, then we
are changing a constant, which is a no-no. However, if used properly, and only
set during the initialization phase of the app (i.e. once), I believe it is a
handy shortcut to having to check for the existence of that variable every time
you want to use the class. Feel free to correct me on this. There is probably a
better way to do it, such as using inheritance, but I found it fascinating that
a solution like this would even work.&lt;/p&gt;

&lt;img src="https://analytics.ptx.sh/p/SjOB3oKbb?id=2CD3G94GKEC5DN0EV6PBQXQEBV&amp;url=%2Fnotes%2Fprogramming%2F2010%2F08%2F05%2Fshapeshifting-classes%2F" alt="" /&gt;
    </content>
  </entry>
  
</feed>
