Edward Loveall

The Stages of Video Game Obsession

While playing a video game, I’ve noticed that I’m usually experiencing one of five stages:

Ramp up

This consists of character creation, tutorials, looking up what things mean, and other beginner tasks. It’s often hard to get past this stage, but my initial excitement (and money spent) usually gets me through it.

Totally obsessed

I can’t stop thinking about this game. It’s all I want to do or read about. Left to my own devices, I would just play it all day, nonstop. I want everyone around me to play it too so I have more excuses to play and talk about it.

Good fun

I like playing the game and still choose to spend time on it. There are many fun challenges left to overcome, but I can also enjoy other activities. When with friends, I still enjoy talking about the game, but I don’t feel the urge to constantly bring it up.

Tedious grind

This happens when I feel I have a few challenges left I want to complete, but I start questioning if it’s worth the time. I still might complete them, and the reward might even feel good, but it often does not justify the work to get there.

Not fun

I’m sick of the game. I am uninterested in playing because it would be boring with little to no reward. I can find myself here if a friend wants me to play with them after I’ve completed the game.

I find that these stages are pretty common and I experience most of them with most video games. If the game is really good about effortlessly teaching you how to play, the first step feels like the second, and that’s really nice. AAA games are often (but not always) pretty bad at this step and can overwhelm you at first.

Your mileage may vary, of course.

Speeding Up PostgreSQL Database Imports

Instead of using one process to import data, you can use multiple with the --jobs=N flag, where N is the number of logical cores you have. It looks something like this:

pg_restore --clean --no-acl --no-owner --jobs=4 -h localhost -d my_app_development production-data.dump

Using -j N also works.

Don’t know how many logical cores you have?

What now?

Trump was elected. My goal now is to help people who need it. I’ve got a lot of work to do.

But how do I choose what to do? Someone once compared learning how to be an activist like leveling up a character in a game. When you start at first level, all you can do is cast “wear safety pin”. That’s a great start, but you’re not going to kill the evil dragon with it.

So you learn other spells, like “join committee”, or “read book”. Eventually, you learn so many spells that one day, you realize you’ve leveled up. Keep at this long enough, and you can now fight that evil dragon.

I know myself and if I try to level up without external motivations, I’ll let things drop. So I hope that making my plans public will help keep me honest and on track. Even if no one actually reads this, the fact that it exists will give me the motivation I need. Maybe you’ll be inspired to do the same.

Here’s a list of things I am doing or plan to start doing in the near future:


RailsBridge (and RailsBridge Boston) is an organization that focuses on teaching underrepresented people in tech to program. I have been a TA at a few events and was recently invited to be an organizer. I’m helping with the next event in January.


I have been mentoring people one at a time for about a year, but this last week I took on one more mentee. I’m focusing on a similar group as RailsBridge, underrepresented people in tech.

Diversity/inclusion group

I joined a diversity/inclusion group through a local Unitarian church. Their goal is to “foster diversity and inclusion at the church, in Massachusetts, and beyond.” They hold meetings every week or so (I think) to talk about issues surrounding race, social class, gender, age, and more.

Reading The Righteous Mind

I heard about this book on a podcast and it piqued my interested. It’s about how the political left and right view morality differently. From the book’s introduction:

My hope is that this book will make conversations about morality, politics, and religion more common, more civil, and more fun, even in mixed company.

Seems useful. My hope is to better understand the people I disagree with so I can then focus on the best ways to talk with them, not at them.

Paying attention to what matters

I want to try and make sure I focus my limited attention on substance not fluff. There are enough terrible events right now to fill a garbage dump, and it’s not going to start smelling sweeter. But not all of them are worth my time. John Gruber summed this up well in his recent post:

Twitter is full of people talking about Mike Pence getting booed by the audience at Hamilton last night. Now Trump himself is tweeting about it, focusing news media on the incident. Booing is not meaningful opposition. But it has served to distract from a legitimate scandal: Trump settling a fraud lawsuit for $25 million yesterday. The smart opposition is focused on that today.

First, I want to be able to recognize the right issues instead of the fluff. Once I can do that, I want to make sure I boost those stories instead of non-stories.

Taking breaks from Twitter

Twitter can enable great things, but the constant emergency state that it can produce is too much sometimes. I took a break from Twitter all of last week. I had a lot more energy to accomplish everything in this blog post, and just felt a lot better. I’m not quitting Twitter or all social networks, but I’ll likely be taking more breaks.

This is a lot, but I have a lot of life left to accomplish it. I’m sure I’ll learn more about how to level up as I go. For now, we’ll see how this goes.

StringScanner: Regular Expressions Made Better

I’ve been using ruby’s StringScanner class a lot lately. It “performs lexical scanning operations on a string” which is a fancy way of saying “read this string from left to right and stop at certain points to tell me what you found.”

It’s similar to using regular expressions. In fact, StringScanner uses regular expressions to get its work done. Let’s look at a contrived example:

dessert_choices = 'Edward enjoys ice cream. Elizabeth enjoys brownies.'
sentences = dessert_choices.split('. ')

We want to extract some data from the sentences, name and dessert. First with regular expressions:

sentences.each do |sentence|
  matches = sentence.match(/(\w+) enjoys ([\w\s]+)/)

  name = matches[1]
  dessert = matches[2]

  puts "#{name}: #{dessert}"

Then with StringScanner:

sentences.each do |sentence|
  scanner = StringScanner.new(sentence)

  name = scanner.scan(/\w+/)
  scanner.skip(/ enjoys /)
  dessert = scanner.scan(/[\w\s]+/)

  puts "#{name}: #{dessert}"

These both print out exactly the same thing:

Edward: ice cream
Elizabeth: brownies

What is StringScanner doing?

StringScanner keeps track of a point in a string and can advance that pointer forward using scan. The pointer starts at the beginning:

Edward enjoys ice cream.

After running scanner.scan(/\w+/), the pointer moves up:

Edward enjoys ice cream.

Every time it scans, it returns the text that was scanned over.

In this case, it begins by scanning for multiple word characters \w+ in a row. Then, it skips over the word enjoys with spaces around it. Finally, it scans for multiple word or space characters [\w\s]+. Every time scan is called, it returns what it found, in this case name and dessert.

Regular expressions can often extract text from strings using only a single line of very compact syntax. StringScanners on the other hand usually need multiple lines to accomplish even these simple tasks. Even in this example, I needed to split up the regular expression into three parts. So why would anyone use StringScanner?

It’s actually because StringScanner is broken up that I like using it. It allows me to partition my code and label discrete operations. Naming is such a huge part of code clarity, and string scanners make this so much easier.

Here’s a refactor of the StringScanner above:

sentences.each do |sentence|
  scanner = StringScanner.new(sentence)
  single_word = /\w+/
  filler = / enjoys /
  multiple_words = /[\w\s]+/

  name = scanner.scan(single_word)
  dessert = scanner.scan(multiple_words)
  puts "#{name}: #{dessert}"

This is even longer, but I’d argue that it’s also easier to read. Some of it even reads like english like scan(single_word) or skip(filler). Even in this contrived example, it’s much cleaner than a relatively simple regular expression like /(\w+) enjoys ([\w\s]+)/.

There are other useful things they can do like reading ahead without advancing the pointer (check) and returning nil when they don’t find a match. The latter is useful for optional parts of a string. I.e. scan for foo and if you don’t find it, continue on. I find that especially when I start using lots of capture groups in my regular expressions that a StringScanner cleans them up.

Try out StringScanner next time you need to extract data from a string.

Rails and Subdomains

About a week ago, I quietly relaunched this blog to run off the same app as my main website. I wanted the transition to be as seamless as possible which meant:

This post will mostly focus on the “same url” part, but I’ll quickly describe how I made the RSS part work.

Preserving RSS posts

RSS items can have a guid. From the RSS spec:

guid stands for globally unique identifier. It’s a string that uniquely identifies the item. When present, an aggregator may choose to use this string to determine if an item is new.

My old blog was hosted on tumblr. It uses the post’s permalink for guids and they look like this:


This is fine for tumblr, but from now on, I’m going to use a reverse DNS system for guids:


To make this work, each post has an optional field called tumblr_guid. This takes the form of the post id. For example, the post above would have a tumblr_guid of 148454710842.

I wanted to keep existing post’s guids the same, so if a post has an existing tumblr_guid, I use that. Otherwise I use a new, reverse-DNS style guid.

If you want to dive into the technical details, here’s the commit with the code.

On to subdomains!

This is going to be a quick tour the steps required to get subdomains working for this blog. It turned out to be pretty simple, after I spent enough time poking around. If you’re looking to do this for your app, just follow along.

The routes

I needed to add routes to manage incoming requests for the blog subdomain. The Rails guides list a subdomain option on the constraint method which sounded exactly right. Here’s an example:

constraints(subdomain: 'blog') do
  get '/', to: 'posts#index', as: :posts

I thought this would work without any other modifications, and it does in theory. But as I found out, it’s not so easy to try out.

The web server

I booted up the app with puma (the default Rails web server) and visited blog.localhost:3000 to test my new routing constraint. Unfortunately depending on the browser, either my subdomain was ignored and Rails rendered the main site or the browser gave me an error.

This is because localhost isn’t a real domain. Real domains use DNS which allow subdomains like blog.edwardloveall.com to work. The best way around this problem is using a service like lvh.me. It’s a domain that redirects requests to localhost. Since it’s a real domain it uses DNS, and subdomains work like you’d expect. If I boot up my server now, I can visit blog.lvh.me:3000 and see my test blog page.

But the site still didn’t load. This is because of what addresses the default Rails server listens to. Starting in version 4.2, it only listens to (i.e. localhost), rather than like it used to. is a reserved IP address that listens to all addresses. So when I boot up my server, I need to bind it to like so:

$ rails s -b

Now I could visit blog.lvh.me:3000!

If you are on wifi in a public place, this is a security risk because anyone on that network with your IP address can access your app. Only use it when you need to.

Curiously, a brand new app with Rails 5 doesn’t seem to need the address binding. I’m not sure what configuration is different but your milage may vary.

The path helpers

So now I had an app responding to subdomains, but I still needed to test it and link to it from my main website.

The solution was to use *_url(subdomain: :blog) helpers everywhere instead of *_path. Path helpers return a relative path which implies the same domain name and completely ignore the subdomain option.

We can see this in the console:

irb> app.posts_path(subdomain: :blog)
=> "/"

irb> app.posts_url(subdomain: :blog)
=> "http://blog.example.com/"

Keep this in mind when:

Here are some code examples:

post = Post.first
redirect_to post_url(post, subdomain: :blog)

<%= link_to 'Blog', root_url(subdomain: :blog) %>

link_to root_url(subdomain: :blog)

expect(current_url).to eq(post_url(post, subdomain: :blog))

And I just want to underscore that *_path helpers with subdomain: :blog does nothing. I can’t tell you how many times I tried to use this.

DNS configuration

The DNS setup was pretty straightforward. I removed my old CNAME record for blog and added it again as an A record pointing toward the same address as the main site.

I’ll use this as an opportunity to say that if domains and DNS confuse the hell out of you, I wrote a book about them. Go check it out if you feel out of your depth with domain names and DNS configurations.

So that’s pretty much it. The rest was going through the motions of adding pretty urls, tests, code highlighting, an RSS feed, and pagination. Like I said, adding the subdomain, once you know the tricks, is pretty simple. Now my blog and portfolio can exist side-by-side in a single app.

Thanks for reading!

Domain Facts

I wrote a book that will teach you everything you need (and quite a bit you don’t) about domains, DNS, and TLS certificates. It’s available today and you can buy it right here.

While writing the book, I learned heaps of information about how the internet works at the DNS level. Most of that information made it into the book, but there are a few interesting bits and pieces that I couldn’t find a home for.

Here’s a grab-bag of facts I’ve collected over the course of writing the book. Some of these might not make a ton of sense if you’re not familiar with DNS. If that is the case, I have a great book recommendation for you.

Every top-level domain

Ever want a full list of all registered TLDs? Here it is. Note that these aren’t all available for registration, and some probably never will be. I doubt .apple or .google will be available to the general public any time soon. There are also certain country TLDs that aren’t available like .aw or .gw.

There’s not much rhyme or reason to why some TLDs are available and some aren’t. Maybe they’re not set up to take registrations, maybe they don’t want anyone outside of their country to snatch up domains for non-country purposes. If these TLDs are ever available, the registry gets to decide when, and how,

Domain registration stats

Registries send a report to ICANN at the end of every month. The reports (found here) are big spreadsheets that contains information like, how many domains were registered, renewed, transferred, etc. by each registrar. Ever been curious how many .club domains were registered in March of 2001? The answer is “none” because .club didn’t exist until May of 2014. But you can get all the information on that TLD since then.

Become a registrar

If you ever wanted to run your own domain registrar like Hover or Gandi, it'sā€¦ actually somewhat daunting to set up. All the steps are outlined over at Verisign. For example, you have to pay ICANN a $3,500 non-refundable fee and prove that you can handle the huge amounts of cash you’ll get as a domain registrar.

How domains are priced

This quora post outlines the process of how a .com domain can cost around $10, but others can be priced in the thousands. (I’m looking at you .car.) In summary, registries (companies that own a TLD) sell domains in bulk to registrars (companies that sell domains to the general public). They can set whatever price they want, but first have to get ICANN to sign off on it. ICANN doesn’t decide prices, but they want to encourage a healthy market.

After registrars know the bulk price, they can price individual domains however they want so customers like us buy them. Prices change by the same process: a registry negotiates with ICANN, registries sell in bulk to registrars, registrars sell individual domains to us.

Public-key encryption is only lightly used

When you visit a site with a TLS certificate (think https), your browser and the site set up a secure connection. All traffic from then on is encrypted and can only be decrypted by you and the website. The technique used to set up the encrypted communication is called public-key encryption.

A dirty secret in the encryption world is that public-key (also called asymmetric) encryption is only used at the start of an encrypted transaction to transfer a key for symmetric encryption, which is much faster.

Asymmetric encryption is still very important. Without transferring that symmetric key, encryption would either be slow or nonexistent, but I used to think public-key encryption was used for all communication on secure websites.

Coolest organization name

Finally, the coolest name for a standards organization goes to: the Internet Engineering Task Force. They publish many RFCs that have set standards since the Internet’s debut. They even set standards for the pre-Internet ARPANET.

While the RFC documents can be a bit dry, there have been a few humorous publications over the years.

If you enjoy learning this kind of thing, check out the book. It covers a lot of similar subjects, but in much greater depth. You’ll learn how to use command line tools to debug a domain, create TLS certificates for your website, and solutions to common scenarios like domain transferring or connecting to an external service. If you’ve ever tried to register or maintain a domain and been totally confused, you’ll love it.

Swift Configuration Objects

I’m working on a project that requires drawing some boxes on the screen. The boxes all behave the same way, but some have different sizes and colors.

To keep track of these sizes, colors, and potentially other settings, I’ve built a Style struct to namespace and organize all variables in one place. A codified Style Guide if you will. Here’s what it looks like:

struct Style {
  static let colors = (
    red: NSColor(red: 0.93, green: 0.47, blue: 0.45, alpha: 1.0),
    green: NSColor(red: 0.65, green: 0.89, blue: 0.67, alpha: 1.0)

  static let sizes = (
    small: CGSize(width: 10, height: 10),
    medium: CGSize(width: 30, height: 30)

This lets me use these sizes and colors like so:

let red = Style.colors.red
let small = Style.sizes.small

Since the constants are tuples, you could, in theory, group the variables by the objects they’ll be used in:

struct Style {
  static let boxA = (
    color: NSColor(red: 0.93, green: 0.47, blue: 0.45, alpha: 1.0),
    size: CGSize(width: 10, height: 10)

  static let boxB = (
    color: NSColor(red: 0.65, green: 0.89, blue: 0.67, alpha: 1.0),
    size: CGSize(width: 30, height: 30)

If this is what you want, I’d suggest an alternative: group them first by their type (size, color, etc.), then use those constants to define other groupings:

struct Style {
  static let colors = (
    red: NSColor(red: 0.93, green: 0.47, blue: 0.45, alpha: 1.0),
    green: NSColor(red: 0.65, green: 0.89, blue: 0.67, alpha: 1.0)

  static let sizes = (
    small: CGSize(width: 10, height: 10),
    medium: CGSize(width: 30, height: 30)

  static let boxA = (
    color: Style.colors.red,
    size: Style.sizes.small

  static let boxB = (
    color: Style.colors.green,
    size: Style.sizes.medium

It feels a little awkward to be referencing the struct inside of itself, but the tradeoffs seems worth it. If you apply red to other properties, (like a stroke color, for example) you can:

This pattern seems useful in projects where a designer has created a formal style guide. This is opposed to having loose-leaf constants scattered about the code, or even collected at the top of a single file.

I’d love to know what you think about it. How do you think it could improve? What other use cases you see it having?


Davide De Franceschi pointed out to me that just by using an enum instead of a struct, I remove the ability to instanciate a Style, which is a good thing.

He also pointed out that I can use enums all the way down:

enum Style {
  enum Colors {
    static let red = NSColor(red: 0.93, green: 0.47, blue: 0.45, alpha: 1.0)
    static let green = NSColor(red: 0.65, green: 0.89, blue: 0.67, alpha: 1.0)

  enum Sizes {
    static let small = CGSize(width: 10, height: 10)
    static let medium = CGSize(width: 30, height: 30)


Building a Waiting git Editor

When I commit to a git repository, I don’t like using a command line editor, but using a GUI editor sometimes takes a while to boot up. I’ve settled on using TextWrangler for now since it opens a window reasonably fast, especially if the app is already open.

I always thought it would be cool to build a dedicated git editor that you can launch from the command line, see a nice diff of my changes, and edit using native Mac text editing. If I ever want to do that, I need to figure out how git creates a commit with an external editor.

My git config for the editor looks like this:

$ git config --get core.editor

edit --wait --new-window

Git will open TextWrangler using a couple of options:

--new-window makes sense to me, but how does --wait work? Well, a bunch of things happen when you type git commit:

(I’m sure it does much more than just that, but this is all I need to know for now.)

Great, so now all I have to do is make an editor that writes text and closes its process when its done. A ruby script will exit automatically when its done running, so if I can create a script to write some text to a file, it should work.

Here’s what I came up with:

#!/usr/bin/env ruby

commit_message_path = ARGV.last
puts File.read(commit_message_path)

print 'Commit Message: '
message = $stdin.gets

File.write(commit_message_path, message)

The first line uses a hashbang to tell the rest of the script to be interpreted as a ruby program.

Then, I grab the last argument passed into the program and print all its contents out to the screen. That way I can see all the changes that have happened since the last commit. This printing is optional.

Next, I give the user a prompt to input their commit message. Once they hit return, I write the commit message to the original file. The ruby process closes, git does its thing, and I have a new commit message!

This is obviously very primitive. It’s still a command line UI, not a GUI. It can’t do multiline strings. In fact, it’s less useful than using the -m option with git commit. But now I know (and so do you) how to build a waiting editor.

The Imperfect Feminist

My friend Casey said to me recently:

For me I just accept that there is no such thing as the perfect feminist.

It made me realize that I had been considering feminism a binary term: you are, or you aren’t. This, in hindsight, is stupid.

Maybe you consider yourself a programmer, or an artist, or a chef. When did you become that? For me, I became a programmer when I switched from being a designer to using Rails full time. But so what? Does that mean I’m done? Absolutely not. I’m still learning how to be a better programmer all the time.

This is now how I feel about being a feminist. I’m a feminist, but that doesn’t mean I’m “done”, or that I won’t make mistakes again, or that I have nothing left to learn.

It doesn’t matter if someone calls themselves a feminist or not. What matters is that they are willing to learn, listen, and get better.

An Incredibly Dumb Way to Make Sentences

For a long time, Markov chains seemed unapproachable to me. I’m not exactly sure why; perhaps they were always brought up in the context of artificial intelligence, or academic math, or their impossible-to-understand Wikipedia page.

I’m here to tell you: Markov chains are easy to understand, especially the first-order ones. Let’s take a look.

Take the following sentence fragment:

the cat and the dog

Look at each word and count the words that come after it:

the -> cat: 1
    -> dog: 1
cat -> and: 1
and -> the: 1

Let’s go through each word in the cat and the dog. the has two words that follow it: cat (the cat) and dog (the dog). cat is followed by and. and is followed by the. With those pairings, the whole sentence is accounted for: we’ve already mapped the the after and, and dog has no words that follow it. The numbers next to each “follower word” are the number of times it appears after the first word. For example, cat appears only once after the.

This is the basic structure of the words in this sentence. It allows us to to make new, similar sentences. We can do that by picking a word at random, then picking one of it’s follower words at random, then repeat. For example, we can randomly start with cat:

cat and the cat and the dog

We stopped at dog because it has no followers. As you can see this is a semi-plausible sentence, and looks quite a bit like our original sentence. Even with the randomness, there’s just not a lot of followers to choose from.

More words

Here’s an excerpt of the word structure from Shakespeare’s Much Ado About Nothing. It’s massive so I’ll only show you some of the structure for “a”:

a -> man: 22
  -> good: 17
  -> very: 7
  -> young: 3
  -> kind: 3
  -> lord: 3
  -> messenger: 2
  -> lady: 2
  -> new: 2
  -> lion: 1
  -> headborough: 1
  -> sexton: 1
  -> lamb: 1
  -> badge: 1
  -> constable: 1
  -> victory: 1
  -> stuffed: 1
  -> skirmish: 1
  -> difference: 1
  -> reasonable: 1
  -> boy: 1

That’s a lot more to work with, and it goes on for quite some time! Here are some examples of the sentences we can generate with all that text:

scholar would modestly examine your answer

husband have you welcome my place

purse such matter there’s a rougher task in your friend

Now, I know what you’re thinking: “Wow! That’s literally as good as Shakespeare!” I know. I used a little something extra to pull off this convincing effect: weighting.

Notice how in the word chain above, man appears 22 times after a, but a word like headborough only appears once. That means, if we come to the word a and we’re picking a follower word, man is 22 times more likely to follow than headborough. This is a weighted algorithm and it will create more plausible sentences.

Second-order Markov chains

We’re just tracking a single follower after each word. This is called a single-order Markov chain. But if we were to extend that to two words, we could have a second-order Markov chain:

the -> cat: 1 -> and: 1
cat -> and: 1 -> the: 1
and -> the: 1 -> dog: 1

The really bad example sentence that I picked is… well, really bad at showing this, but now we have two words to look at when choosing a follower word. That is, if we generate the cat, we can see that it’s always followed by and. This can give us more realistic sentences because it has more context.

Learning a new programming language

A Markov chain is now my go-to project for learning a new programming language. It’s relatively simple and gets me working with basic data structures, file loading, randomness, and loops. I recently started learning Swift and made one.

Pun generator

However, programming a Markov chain won’t expose you to all parts of a language. My friend Gabe wrote a blog post about learning a new programming language that outlines the steps to make a pun generator. It is a fantastic post that will end in you having a program that will generate the lamest of puns.

I went through it and created a Swift version.

I’m writing this post as sort of a prequel to Gabe’s. I found the pun generator to be a large undertaking compared to a Markov chain. If you’re looking for a something between “hello world” and generating puns, I suggest you give Markov chains a try.