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.

Anyway, I wanted get the hello world app working on ruby. Apparently rails new (sitename) will create an app, and rails server will run it. I had a little trouble with port forwarding on Windows. Launching the app with rails server works, in the sense that it launches the app and that other shell windows that are SSHed into my VM can do curl localhost:3000 and see a response. But it doesn’t work in that I can’t call localhost:3000 from my host machine. I tried configuring some different ports in my Vagrantfile, but without any luck. Then I found some post (which I can’t find again to give credit to, sadly) saying that instead of rails server, I should run bundle exec puma -C config/puma.rb to force the server to use the config file. This worked, and the port on my host machine that is forwarded to 3000 on the guest machine indeed hits the rails server now. First difficulty cleared.

The second difficulty was when I scaffolded a “Users” table using rails generate scaffold User name:string email:string. That command succeeded, but every time I tried to browse to localhost:3000/users, I would get an exception from the JavaScript runtime. I found a StackOverflow answer that suggested installing node, rather than letting ExecJs try to handle rails. That fixed the problem. The post goes on to suggest that I could fix the problem without installing node, by editing ExecJs’s runtimes.rb file, but node is so widely used now that I don’t feel bad taking it as a dependency.

In short, running on through the toy app part of the rails tutorial book works fine, with the two differences:

  1. We need to launch the server with bundle exec puma -C config/puma.rb instead of with rails server
  2. We need to either install node, or make some changes to ExecJs’s file called runtimes.rb.

Next time, we’ll try to make some more progress into the rails tutorial book.

Till then, happy learning!


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s