Enter the void *

Santa made me learn Rails in a week

by Etienne Millon on April 3, 2015

Tagged as: rails, secretsanta.

Abstract: I released Secret Santa Creator, a free website to organize events where every participant makes a gift to a random other one. To do that I learnt Ruby on Rails in a week and it was awesome. As usual I put the source on Github.

Every year I take part in Secret Santa: within a group of friends, everyone has a “target” to whom he has to make a gift.

There are several techniques to organize that. The simplest one is to have anyone put their name in a hat, shuffle everything, and have everyone pick one name. But to do that, you need to put everyone in the same room before the event and that is not always convenient. Another possibility is to ask someone to pick the names, but he will know who has to make a gift to him.

So last year, I decided to script this. I made a small python script that takes a list of names and emails, shuffles them and sends email to the correct persons. It worked well. Technically, I could know who was supposed to make me a gift by watching my mail logs, but short of sophisticated cryptographic protocols, you have to trust the organizer not to cheat anyway.

In a way, this was a good MVP; but it was not very reusable. Indeed, some friends asked me the program so that they could use it with other friends, but I could not expect everybody to have python and sendmail installed on their machines. To cover their needs, it turns out that there are a lot of websites that offer this service, so I ended up pointing them to these websites.

This year, I was asked again about how to organize a Secret Santa, so I figured, why not build a website? This had the opportunity to be directly useful to my friends, so I jumped in. Plus, this was a good excuse to learn new technologies. I gave myself one week to learn Ruby on Rails, code the website and deploy it on Heroku. That is what the cool kids do, right?

My web stack of choice usually revolves around Flask, which is simple and powerful, but it does not do a lot of things out of the box. That is one the strengths of this microframework, but I wanted to try something more integrated. Django would have been a good choice too, but I was curious about Ruby on Rails and the Ruby ecosystem in general.

I had bookmarked the Ruby on Rails Tutorial by Michael Hartl, which seemed a good resource. Indeed, it is very nice, seems it is up to date and emphasizes not only on the code but also on how to deploy a project, or even how to keep a project under source control. When you learn a new technology, it is not obvious which files should get checked in. If you asked me before, I would probably have put Gemfile.lock out of git.

The book uses particular versions of the different gems, so this has been tested and works flawlessly. At first I was afraid to have to use rvm, which I heard does not work too well. I prefer using a ruby interpreter provided by my distribution, but I am OK with using third-party gems. That is my policy for Python too: I use a system python and a virtualenv for each project. Ruby’s bundler seems to work like this.

I was very pleased by the first chapter of the book which explains how to write a minimal rails site and immediately deploying it to Heroku. I found it astonishing that to do that, absolutely zero configuration was needed. That is in part thanks to Rails’ Convention over Configuration philosophy and in part because Heroku is made for Rails app by default.

By contrast, to deploy a Flask app these days on a server I control, I have to write an Ansible playbook. Mostly copy & pasted from previous projects but still, the friction is incomparable. This is not specific to Rails though, so I may use Heroku for Python one-off projects too now.

The rest of the book focuses on creating a microblog site, first using the scaffold technique and then by hand.

I liked that there is a lot of structure in Rails application: everything has a “correct place” and there is a clear separation between everything. Even tests are automatically separated into different folders. Also, I have not created a single .rb file by hand; everything was created by rails generate. This is the sweet spot between having to do everything by hand and coding in an IDE.

As for the Ruby language itself, I figured that I would learn it on the fly since it is similar enough to Python. That worked out well.

I like the :symbols a lot, they remind me of Lisp. It makes a clear distinction between strings used as keys and strings that are meant to be printed. I am not a fan of the colon syntax itself, especially when they are mixed with hashes (k: :v) but syntax highlighting helps in that case of course.

The concrete syntax is a bit weird. I like the explicit end, but I am still not sure whether whitespace is significant. Same goes for expressions: it is a bit unclear when parentheses are needed. I think that it is the same as in Coffeescript. I hope that it is not ambiguous and that bugs arising from that are rare.

That should be covered by tests anyway. The book encourages to write a lot of tests, which is quite nice. The testing ecosystem is interesting, particularly minitest and guard, which make TDD very easy. Guard is a bit too aggressive, which means that it will sometimes not run all the needed tests. This is probably just a matter of writing a better Guardfile.

Anyway, I went through chapters 1 to 9 and it was enough to get a good grasp of how to code a Rails site.

The website I wanted to write would work like this:

It is actually a bit more complicated since it also handles edition, but overall it is a very simple website. With the Rails Tutorial almost done I had enough to build it. Actually, Secret Santa Creator is even simpler since it does not require authentication. I did it mostly using Test-Driven Development, as in the tutorial.

The hardest part was definitely creating nested forms. Every event has a list of participants, and a list of constraints. It is thus necessary to create a form that can edit this list structure, by directly editing participants or constraints from the “edit event” form, but also removing or adding some.

I found the cocoon gem which works fine for this, and I could build this kind of form:

Nested forms with cocoon

Nested forms with cocoon

To send email in my Python script MVP, I just piped stuff to sendmail. Fortunately, Ruby on Rails has an integrated system to do that, with Action Mailer. You just need to setup SMTP configuration and write rails generate mailer and boom, you can send emails. Heroku has a plugin for sendgrid with a reasonable free tier, so I used that.

Coding the actual website took approximately two days. It is possible to be that fast only because Rails insists that easy tasks should become no-brainers.

You can see the site here and the source on Github.

It works reasonably fine, barring a few quirks in the UI. I used it myself to organize several events this year, and a couple friends did the same. I would call that a success! I plan to work a bit more on it at the end of the year and try to get a little more users. I am curious to see how it goes!