Book Review: Algorithms to Live By

This post is a review of Algorithms to Live By: The Computer Science of Human Decisions by Brian Christian and Tom Griffiths (Amazon, Audible).

I love this book, but its title might be a slight exaggeration. I would have called it Some analogies of varying strength between computer science questions and life questions, with some special focus on optimal stopping, sorting, scheduling, and game theory. I guess that doesn’t have quite the same ring to it.  Continue reading “Book Review: Algorithms to Live By”

Make a Simple Gem

In the time I’ve spent learning to code, I often see a little uptick in difficulty around packages (or dll’s, or gems, or imports, or whatever). Getting to “hello world” is pretty easy, but then getting to a program that prints hello world but also imports some system library for regexes or whatever is slightly harder, and often not covered well in tutorials. So I think that part of basic competency in a language is being able to publish and consume bundled code. I’ve been learning Ruby recently, so I’m going to do three things in this post and the following post:

  1. Go through making a gem for myself to use in a silly web app.
  2. Import said gem and use it.
  3. Import some published gem and use that.

Continue reading “Make a Simple Gem”

A Very Simple Vagrant Deployment

Last week, I looked at the getting a rails server pushed up to AWS using a Vagrant. After that was working, I decided I wanted to be able to test changes on a local VM, then push that VM to the cloud when I liked it, rather than test all my changes in the cloud.

In the directory where I had the Vagrantfile and the shared folder for the rails server, I did vagrant up --provider=virtualbox, and I got this:

An active machine was found with a different provider. Vagrant
currently allows each machine to be brought up with only a single
provider at a time. A future version will remove this limitation.
Until then, please destroy the existing machine to up with a new

Machine name: default
Active provider: aws
Requested provider: virtualbox

Continue reading “A Very Simple Vagrant Deployment”

Simple Rails Server on AWS with Vagrant

Last time, we learned why vagrant up with the AWS provider sometimes hangs on “waiting for SSH to become ready” (because I accidentally set it to use a private IP, but didn’t map routes or anything), and why it sometimes says “invalid group ID” (because if the group id provided doesn’t match your security role and region, AWS reports the same error as if you’d passed in a null group id).

Now, I’m going to resume doing the rails tutrial book’s “mostly static pages” and try to deploy it in AWS. I’m not going to worry about DNS entries for this post – I’ll declare victory when I can paste the public DNS entry that AWS generates for my instance in the browser and see some Rails content come back. Continue reading “Simple Rails Server on AWS with Vagrant”

Vagrant in the Cloud

My goal for this post is to take the sample app steps from the rails tutorial book, work on them locally, and deploy them in AWS from a script. Then I will share the script. To start with, I have a Vagrantfile that works fine for doing rails development locally, and I have an AWS account. One of the first things I did was set environment variables on my host machine to store my AWS credentials in. Then I can refer to those environment variables in my Vagranfiles, and I don’t need to risk checking an API key into github or something. In the vagrant file, it looks like this:

aws.secret_access_key = ENV['AWS_SECRET_KEY']

And then in my ~/.profile:

export AWS_SECRET_KEY="Wouldn't you like to know"

Then I made a new directory and copied my vagrantfile locally, and began modifying it based on an example vagranfile here. Continue reading “Vagrant in the Cloud”

More Portable Vagrancy

Last time, I talked about finding a pre-made vagrant box that would be useful for rails development. I found one that’s pretty good, but it turns out not to be perfect. I decided to try to write my own Vagrantfile for getting a simpl rails server running on localhost, and I came up with the following success criterion:

No care or feeding. In other words, I could open the vagrant file, and run the following commands straight through and have them just work:

  1. vagrant up --provision
  2. vagrant ssh
  3. cd /vagrant
  4. rails new toy_app
  5. cd toy_app
  6. rails server

And then in the host machine, browsing to localhost:3000 should show the standard “hello from rails” screen. Anything less than that and I feel like I’m sacrificing the real benefit of Vagrant, namely, a repeatable, portable environment setup.

I am doing this by iterative experiment. I started with a Vagrantfile that was empty except for setting the base image of ubuntu/trusty64.

Each iteration, I run vagrant up --provision, then ssh into the box, then try to start a rails server. If I get an error (or am missing a dependency), I exit the ssh session, edit the Vagrantfile, and reload the vm. Periodically, I destroy the vm to make sure that I’m not dependent on some sequence of shell commands I happened to run.

One thing I’ve found useful is this command:

cp $HISTFILE /vagrant/history.txt

It copies the list of shell commands that I’ve run (since the last time I destroyed the vm) into the shared folder, so I can access them from the host machine. That way, if I manage to do something important while I’m ssh’ed into the box, I can read the steps carefully when I’m trying to figure out how to add them to the Vagrantfile so that they become a repeatable part of the environment.

The following Vagrantfile almost passes the test:

# -*- mode: ruby -*-
# vi: set ft=ruby :
# All Vagrant configuration is done below. The "2" in Vagrant.configure
# configures the configuration version (we support older styles for
# backwards compatibility). Please don't change it unless you know what
# you're doing.
Vagrant.configure("2") do |config| = "ubuntu/trusty64" "forwarded_port", guest: 3000, host: 3000
# runs as root
config.vm.provision "shell", inline: <<-SHELL
apt-get update
git –version || apt-get install -y git
rails –version || apt-get install -y ruby-railties-4.0
nodejs –version || apt-get install -y nodejs
# runs as non-root user "vagrant"
config.vm.provision "shell", privileged: false, inline: <<-SCRIPT
gpg –keyserver hkp:// –recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3
curl -sSL | bash -s stable –rails
source /home/vagrant/.rvm/scripts/rvm
rbenv install 2.0.0-p353
rbenv global 2.0.0-p353
yes | gem update
gem install rdoc
gem install rails pg
if [ ! -d "/vagrant/toy_app" ]; then
(cd /vagrant && rails new toy_app)
(cd /vagrant/toy_app && bundle install)

What it’s still missing is that rails server doesn’t quite do what it should; for some reason, running rails server will launch the rails server just fine, but will not enable port forwarding, and for that I need to run bundle exec puma -C config/puma.rb. Next time, I’ll try to figure out why the default commands executed by rails ignore config/puma.rb. Also, there are a few warnings printed to the terminal when I vagrant up -- provision from that file. I haven’t noticed any ill effects yet, but I might still try to chase down the errors in a future post.

Till next time, happy learning!


More Ruby on Rails on Vagrant

Eric Lippert has a post where he talks about idempotencce. He points out that in programming when we say a function is idempotent we mean:

the effect of the function … is invariant over the number of calls.

In other words, if we call the same function over and over again, the state of the system will be the same as if we’d called the function only once. That can be a big help, because the invariant “this function has been called at least once” is a ton easier to maintain than the invariant “this function has been called exactly once.”

I like idempotence in configuration and set up code. Let’s take a line from my Vagrantfile for this project. (It’s inside an call to the shell script. In Ruby it’s a string literal; we’re interested in what it does in the shell.)

git --version || apt-get install -y git

In other words, “If git is installed, do nothing; otherwise install git.” You’ll notice that no matter how often I run this line, I’ll always have git installed, but the installer won’t check update or anything except for the first time this is run. This is awesome in configuration, because it lets us write commands that say “assert that this is installed,” and not have to remove them later.

Ok, so idempotent is a favorite word, but I’m done talking about it for now. Let’s move on getting some rails done. For this post, I’m going to do part of the rails tutorial book, but I’m going to use this little Vagrant VM we’re working on as the development environment.

Continue reading “More Ruby on Rails on Vagrant”