I went to tour a local chocolate factory, and things did not go as planned. The place was hopping, all of the walk-in spots on the tour were taken, and they didn’t take reservations in advance. My disappointment was lifted by free samples and a nearby brewery, but I remember someone at the factory saying, “There has to be a better way.”

Inspired to create something that would help them, I e-mailed the factory. Two weeks later, I had built a reservations platform in Rails 5, and they were using it.

Rails lets developers focus on the hard stuff. Few other frameworks would let me completely focus on business needs and get something out so quickly.

What’s the hard stuff?

Here’s what shouldn’t be hard when first building an application:

Accounting for low-bandwidth connections

Supporting a wide array of browsers

Implementing a test framework and writing tests

Choosing and configuring build tools

Setting up a database

Setting up hosting

Adding basic security (CSRF protection, user authentication)

Making big decisions about JavaScript – choosing an MVC, for instance

Here’s what shouldbe hard:

Creating a great user experience

Making sure the features make sense for the intended customers

Defining a data model that makes sense

Writing maintainable code

Working on an app on nights and weekends taught me the value of focusing on what should be hard and letting Rails handle the rest.

Heroku has a beta feature called release phase that allows you to run commands automatically when you deploy your app. The commands run in a separate process before your app is made available to users.

The most common use case for Rails developers to is automatically run database migrations on deploy.

There are other ways to auto-run migrations. In the past, I’ve done this in CI. Release phases are generally better, since they run migrations before your app is available to users. This way, you avoid serving your new release while migrations are still running.

This is awesome for handling failed migrations. If a migration fails, the new release is aborted without impacting users. Because Rails migrations operate within a transaction, your database will be just as it was before the failure.

A (very) quick walkthrough

Just about every app on Heroku has a Procfile at its root. Here’s what a typical Procfile with release phase looks like:

1

2

web:bundle exec puma-Cconfig/puma.rb

release:bundle exec rake db:migrate

That’s. It. Migrations will run automatically each time you deploy, before the new release is available to users. This is Heroku at its seamless best.

Decorators, at the beginning of my Rails journey, seemed exotic and unnecessary.

Draper, a popular gem for decorators, calls them an “object-oriented layer of presentation logic to your Rails application.” I struggled to see the practical benefit.

A particular use case sold me on decorators’ benefits.

Use case: default field values

TourExec is a Rails app that helps businesses take reservations online.

When customers make a reservation, they see a friendly introduction from the business. TourExec provides a default introduction, which a business can override with a custom one.

In the database, the business’s intro field is blank unless they’ve added a custom introduction. We need to show the default intro if the field is blank, or show the custom intro if the field is filled.

You might wonder why I don’t store the default right in the database. The default text is dynamic, based on the business’s name (which can change), and I want the flexibility to retroactively change the default text.

Option 1: Use conditionals in views

I could use conditionals within views to show either the default or the custom intro:

- if @business.intro.present?
= @business.intro
- else
We're excited to have you on a tour at #{@business.name}!

This approach fell apart when I started building the form for businesses to update their intro message. I wanted businesses to see the default and be able to tweak or replace it.

I had to hijack the form helper to show the default if the field was blank.

- f.input :intro, value: (
(@business.intro.present? && @business.intro) ||
"We're excited to have you on a tour at #{@business.name}!")

This felt messy and unclear.

Option 2: Use the model

I considered overriding the “intro” method in the Business model to return the default if the intro was blank.

# app/models/business.rb
...
def intro
(attributes["intro"].present? && attributes["intro"]) ||
"We're excited to have you on a tour at #{name}!"
end

It felt wrong to add presentation logic to the model. If I wanted to use HTML in the default message, I’d have to use raw HTML in the model or bring in ActionView helpers, which have no place in a model.

Option 3: Use a decorator

Decorators handle “presentation logic” for your models. That is, if a model’s fields should be shown in a certain way, the decorator is responsible for making that happen. Draper is a great tool for quickly implementing decorators.

First, I installed the draper gem. Then, I created a decorator for businesses.

Consider introducing separation in your Ruby on Rails monolith with some simple techniques.

At TourExec, half the app is for the public, and the other half is for admins. They’re very different. Admin has a nav bar; public doesn’t. Admin uses Trix; public doesn’t. Public uses Stripe’s JavaScript library; admin doesn’t. The list goes on.

Everything lives in one Ruby on Rails app, and I like it that way. I’m one person maintaining TourExec, and separating out into multiple apps would create too much of a maintenance burden.

Here are some simple techniques to separate sections of your Rails monolith that serve different purposes.

Multiple layouts

The public section of TourExec is pretty minimal:

Admin has a fuller layout, with a navigation bar:

I could continue using one application layout and conditionally include the navigation bar in admin. Instead, I use separate layouts for admin and public.

Create two layouts

app/views/layouts/admin.html.haml

app/views/layouts/public.html.haml

In each of your controllers, specify which layout to use

1

2

3

classAdminController<ApplicationController

layout"admin"

end

Use multiple JavaScript manifests

Public and admin use very different JavaScript. I want to avoid any risk of conflict between the two sections’ JavaScript code.

Separate the default manifest

Typically, in an app, you’d have one JavaScript manifest, like so:

/app/assets/javascripts/application.js

TourExec has two:

/app/assets/javascripts/admin.js

/app/assets/javascripts/public.js

Each manifest brings in appropriate JavaScript for that section. Here’s a peek at admin.js:

1

2

3

//= require trix

//= require pusher

//= require_tree ./admin

I place any custom JS for the admin section in app/assets/javascripts/admin, which is included by the manifest.

Tell Rails to precompile both manifests

To make Rails recognize both manifests so I can use them in layouts, I added this to /config/initializers/assets.rb:

1

Rails.application.config.assets.precompile+=%w(public.js admin.js)

Update your layouts to use each manifest

Our admin layout uses:

1

=javascript_include_tag"admin"

Our public layout uses:

1

=javascript_include_tag"public"

Separate styles?

I could create separate CSS manifests, one for admin and one for public, but didn’t find it worth it. Instead, styles are namespaced with BEM and organized into topical folders in app/assets/stylesheets/. This provides solid separation and the ability to re-use styles throughout the app.

Namespace controllers

In TourExec, there’s a parent admin controller and a parent public controller. Other controllers inherit from one of them.

Here is a preview of the structure:

ApplicationController

AdminController

Admin::ToursController

…

PublicController

Public::ToursController

…

Remember when we specified which layout to use in each controller? Thanks to inheritance, you can specify the admin layout in the AdminController and the public layout in the PublicController, and their child controllers will use the layout as well.

Starting with a monolith

At first, your app may not require any of these techniques. As it grows, you may start introducing some separation to keep things sane. At sufficient scale, you may consider more formal approaches like component-based architecture.

Overall, I find it most efficient to keep apps monolithic for as long as possible, using simple techniques to keep things clean and maintainable. You’ll know when it’s not working anymore, and when a different architecture might be required.

You could realize similar preformance benefits with a client-side app written in a JavaScript MVC that talks to the server through an API.

Turbolinks’ genius is that delivers the improved user experience of a client-driven app without you having to write a client-driven app.

Consider it, every time

You should strongly consider Turbolinks 5 for any new Rails project.

I didn’t consider previous versions of Turbolinks. Superficially, they seemed buggy. Turbolinks 5 is a full rewrite, and it’s been running swimmingly in production for Basecamp 3 and my little project, TourExec.

Why consider Turbolinks now?

Because your users deserve the fastest possible experience, and you deserve to ship quickly.

When I built TourExec, a tour booking platform, I wanted an excellent booking experience for customers. Simply, they choose a time and how many they are, and the app displays available times. Then, hopefully they click a time and book.

Notice in the interaction there is no page reload. The user chooses a date, and the times dynamically update. When the user clicks a time, the booking form appears almost instantly.

This is driven by Turbolinks. I didn’t write any JavaScript to retrieve and display times based on the selected date. I only wired the list selectors to “refresh” the page when the user changed them. Turbolinks takes care of the rest, retrieving the new page body from the server and swapping it out.

This is the most advanced implementation of Turbolinks in my app. The rest of its benefits apply without any extra work.

My admin interface for businesses is super snappy, thanks to Turbolinks. At the point of sale with a line of customers waiting, a business benefits from a tour roster that loads in a third of the time.

Pairing Turbolinks with a JavaScript MVC

I pull in React for some particularly interactive features, like a schedule builder that lets businesses define their tour times. In that case, it was easier to write React components than figure out a server-driven approach that delivered an acceptable experience.

Too often, frameworks like React grow to take over an entire application without a true analysis of the pros and cons.

In the case of TourExec, Turbolinks delivers a speedy experience throughout, and I bring in React for particular needs. This balance allows us to move quickly and reduces technical debt down the road.

The trade-offs

Nothing is without a trade-off. Turbolinks won’t work effortlessly with every JavaScript plugin, but its developers have documented how to adapt, and I’ve found it very doable.

I’ve open sourced RSS to API, which allows you to retrieve RSS feeds via JavaScript. With a few clicks, you can deploy it to Heroku and start consuming RSS from your JavaScript code!

Almost any site with an RSS fee returns a reverse-chronological list of items, each containing a title, link, and date. This consistency can be powerful. You can create a dashboard with the latest feed item(s) from multiple sites. You can bring your corporate web site’s news items on your intranet. The possibilities are limited only by what is available online.

In many cases, it makes sense to grab RSS feeds via JavaScript and display them in the browser. However, cross-domain restrictions generally prevent direct retrieval of feeds via JavaScript. The Google Feed API provided an easy way to retrieve feeds with JavaScript, but it was deprecated in April of 2015 and could disappear at any moment. Alternatives like the Feedly API do not accept requests directly from JavaScript.

To consume RSS in JavaScript, it’s necessary to route it through a server. Your JavaScript communicates with a server, which retrieves the feed and returns it. Google Feed API is going away, and it’s a pain to build your own, so I’m releasing RSS to API. It’s a lightweight Ruby app that accepts requests for feeds and implements caching to serve them quickly. With just a few clicks, you can deploy it onto Heroku’s free plan (you’ll want to up your plan to use this in production).

RSS to API has been tested with dozens of feeds on one page. See the example below, which might lag because Heroku’s free plan has to go to sleep once in a while.

Intro

This tutorial walks through adding e-mail to a Rails app, using MailChimp and Mandrill. We will:

Add new users to a mailing list

Send a welcome e-mail to new users

Alert users when something happens in the app

Our example app is Puppify, an aggregator of cute puppy videos. Read the tutorial, and then check out the source.

Mailing lists vs. transactional e-mails

It is important to distinguish your app’s mailing list from its transactional e-mails. Generally, a mailing list is used for periodic announcements and marketing e-mails, while transactional e-mails are used to notify individual users of specific events.

Mailing lists

Mailing lists handle messages sent to all or many of your users. For instance, you might send a monthly update about new features, or promote a sale on gift certificates.

MailChimp is a popular tool for managing mailing lists. It’s free for many smaller lists.

Transactional

Transactional e-mails are sent to individual users in response to particular events.

Events might include:

The customer was billed.

A new video was posted to a category that the customer chose to monitor.

If you start reading text before the images are fully loaded, these page jumps can be very distracting. On slower connections, images may take a few seconds to load, creating an unpleasant experience for the user and compromising your first impression.

There is a quick fix to avoiding this issue on your own web pages.

The page jumps occur because the browser does not know the width and height of the images in advance. On a responsive site, the image could be a different height and width depending on the screen size.

We may, however, know the ratio of the image’s height to its width. That will not change for a given image, no matter the screen size.

It’s easy to find an images height to width ratio:

Image height / Image width * 100

For the images in our example, we found the ratio:

217px / 325px * 100 = 66.769230769

With this information, we can place a container around the image that will reserve its place, eliminating page jerk.

To start, place a div element around your image, and give it a class like .image-container. All images with this class must have the same height to width ratio.

1

2

3

4

<div class="image-container">

<img src="image.jpg"/>

</div>

In your CSS, give the .image-container a padding-bottom equal to the height to width ratio, as a percentage. Above, we calculated 66.769230769. Include all of the numbers after the decimal for a precise result.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

.image-container{

position:relative;

padding-bottom:66.78082192%;/* ratio of image height to width */

height:0;

overflow:hidden;

}

.image-containerimg{

position:absolute;

top:0;

left:0;

width:100%;

}

Now, the browser leaves room for the image, eliminating page jerk. The page load is much smoother:

The blank space may look odd as the page loads. We can extend our trick to show a placeholder:

To accomodate different aspect ratios, create multiple image containers and use them where appropriate. Use this technique only where the aspect ratio is certain; images that don’t fit the aspect ratio will look distorted.

A common challenge in responsive design – not just with this technique – is maintaining the right image quality for each screen. Check out the Smashing Magazine article below for ideas on this.

When a user registers for your app, you might want to add them to your mailing list. This normally takes a few seconds, as your app has to communicate with the mailing list provider. Still, the user should not have to wait, so we’ll immediately bring the user to the next page while subscribing them to the mailing list in the background.

This example uses MailChimp for the mailing list and Devise for authentication, but Active Job does not depend on either. The example uses gibbon gem to communicate with MailChimp, and dotenv to store the MailChimp API key and list ID as environment variables on dev.

First, add a job for adding a user to the mailing list.

1

bin/rails generate job subscribe_user_to_mailing_list

This generates a new job:

1

2

3

4

5

6

7

8

# app/jobs/subscribe_user_to_mailing_list.rb

classSubscribeUserToMailingListJob<ActiveJob::Base

queue_as:default

def perform(*args)

# Do something later

end

end

Next, customize the job to accept a user parameter, and subscribe that user to the MailChimp list.

Notice that we are passing the newly created user to the job, which then subscribes them to the mailing list.

Active Job is smart enough to realize that we don’t currently have a background job backend, so it performs the action right away, thus making the user wait. Once you add a backend, let Active Job know and you’ll have yourself a true background job. There are many backends to choose from, including Delayed Job, Sidekiq, and Resque,

Performing tasks in the background and eliminating delays for users has never been easier, thanks to Rails 4.2 and Active Job.