Jacob Swanner Development Blog

RailsDiff Rewrite

TL;DR

RailsDiff is now an Ember app, built using Ember CLI, and it gets its data from a new API built using Sinatra.

Yesterday morning I released a complete rewrite of RailsDiff, which just so happened to be exactly 31 months since I first launched the site. This new version uses a completely different architecture from the previous; this post is to describe some of the motivations behind the changes, and how those changes were made.

Wait, what’s the point of RailsDiff?

As of yesterday, one out of my six colleagues that predominantly work with Ruby and Rails still didn’t know the purpose of RailsDiff. I’ve obviously done a good job getting the word out.

When you are going to upgrade a Rails application, RailsDiff is there to help you. It shows you what has changed in the default configurations between the version you are currently using and that to which you want to upgrade. The post where RailsDiff was announced goes into a bit more detail.

RailsDiff is about what you should change about your application’s configuration when upgrading Rails versions, not about what Rails has changed internally.

Motivation for the change

When I started this rewrite, my goal was not to use the latest, shiny tools available; instead it was to solve some real problems that I was having. And, in order to explain those problems, I believe a short review of how the app/site was built previously is in order.

The old implementation was a static site hosted on GitHub Pages. I had good reasons to build the site that way at the time. GitHub Pages is free, and I didn’t need an application to generate diffs on-demand because once a diff is generated it won’t change.

In order to have a static site, something needs to generate HTML files, and for that I turned to Rake. I actually made extensive use of Rake for RailsDiff, I used it to:

  • Generate a new Rails app with each new release of Rails
  • Generate a diff between each new app and all those that came before it
  • Generate HTML files for each new diff

And, I was quite happy with that implementation. I really liked the process of updating the site when a new version of Rails was released, which usually took about a minute to do:

  • rake to generate all the new files
  • git add -A
  • git commit
  • git push origin gh-pages to deploy the site

But, after 2.5 years and many releases of Rails this approach did have its downsides – most notably in disk space. It was approaching 5GB of generated, static files and growing exponentially faster with each new releases of Rails. Which caused me to be reluctant to add new features to the site, because that would mean more HTML files for each release, and even faster growth of disk space usage. I was also worried about the impact on collaborators, if step 1 was giving up 5GB+ of their hard drive space.

Before

Better, stronger, faster

Something needed to change, and the place I decided to start was with the HTML files, as they were taking up the majority of the space. That meant dynamically rendering the diffs as HTML, but I also wanted to keep it a static site for its ease of hosting and speedy responses; using a client-side JavaScript application to do the rendering seemed to meet all the criteria. I chose Ember mostly because of all of the JavaScript frameworks currently available it’s the one I’m most familiar with, and the one we at Envy have the most experience with.

The first pass at the rewrite still had the diffs generated with Rake, which I put into the /public directory of the Ember CLI app; this had the unfortunate side effect of all those diff files being copied to the /dist directory on build, which slowed down the build process, and meant I wasn’t saving as much disk space. I eventually worked around this downside by moving the diffs out of the /public directory and instead modifying the build process to copy the files over, which meant for development builds I could just copy a subset of the diff files; this too was less than ideal, but at least kept development build faster.

At that point I had a working application, but I needed to figure out the deployment strategy. Having enjoyed my experience with GitHub Pages up to that point, I wanted to continue to use it. Unfortunately it’s not a great host for Ember applications unless you use HashLocation (location: 'hash' in the router), which I preferred to avoid. The next option was to deploy to Heroku using the buildpack suggested by Ember CLI. But, this didn’t actually work for me, because all of the diff files made the resulting application slug larger than Heroku allowed limit, which led to me modifying that buildpack to host pre-built Ember apps.

After updating the UI, adding support for legacy URLs, and some other general polishing of the application, I was ready to release it. I was still a bit worried about the disk usage issue, as generating the diff files still had an exponential growth curve. That’s when a couple of my colleagues (Dray & Nate) convinced me that I needed to make an API app to generate the diff files on-demand; the reason being that only generating a new Rails app with each new release, and not the differences between all the releases, leads to a linear growth curve.

Result

After

And, that’s where we are today. There are now two apps to be maintained: one for UI & behavior, and the other for data. Each with their own deployment schemes, their own narrow focus, and their own optimizations. It’s been a lot of effort and in the end, I’m very happy with the result. Hopefully, you will enjoy these changes as well.

If you see a problem with these changes or anything else that can be improved, please let us know.