Category Archives: Rails

Rails lets us focus on the hard stuff

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 should be 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.

CSRF protection? Stick to Rails conventions. Testing? Use RSpec, a de-facto Rails community default. User auth? Add a gem like Devise. Build tools? Use built-in Sprockets. Hosting? It’s a breeze with Heroku and Rails 5. Accounting for low-bandwidth connections? Try Turbolinks (more on this below).

Staying focused on business needs, and letting Rails handle the rest, was the only way to ship.

Rails’ nice surprises

I was overseas recently and the internet sucked. Many web sites didn’t load at all. Some would show a layout but no text; others would show a nav bar and nothing else.

My reservation platform loaded quickly. Navigating the app was zippy.

How was this possible? Believe it or not, the improved Turbolinks. Avoiding full-page reload more than halves load time on bad connections. It took no effort on my part; it’s a Rails default.

A time and a place

A couple of years ago, I implemented React at Cook Smarts, a meal planning app. It transformed our JavaScript from spaghetti to well-structured, understandable code with fewer bugs.

Nonetheless, most of Cook Smarts remained vanilla Rails, views and all. We used React surgically, only when a very high level of interactivity was necessary.

Why stick with vanilla Rails? To keep the focus on what should be hard, building new features, rather than restructuring our app to JavaScript MVC with questionable benefits for users.

Frameworks like Rails get this. Next time you build an app, consider a framework that keeps your focus on what should be hard.

Run Rails migrations automatically on Heroku

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:

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.

So, if you have a Rails app on Heroku, check out release phase!

A case for decorators in Rails

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.

Screen Shot 2016-08-06 at 7.13.49 PM

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 [email protected]}!

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.

Screen Shot 2016-08-06 at 7.18.33 PM

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 [email protected]}!")

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.

# app/decorators/business.rb

class BusinessDecorator < Draper::Decorator
  delegate_all

  def intro
    if object.intro.present?
      object.intro
    else
      "Book a tour with #{object.name} below!"
    end
  end
end

The decorator introduces an intro method on top of the model. It can reach into the model’s intro method with object.intro to grab the actual field value.

When I set @business in my controllers, I have to decorate the object:

@business = current_user.business.decorate

Now, in views, I can reference the field as I normally would.

= @business.intro

And I have to do absolutely nothing to my form helpers:

- f.input :intro

Decorators won!

For this implementation of default field values, decorators seem the best option. I’d love your thoughts and feedback in the comments.

More about decorators

Decorators can do a lot more, like:

  • Show a date field in a particular format throughout your app
  • Show a status field with particular language throughout your app
  • Anything else that involves showing data from your models in a particular way

Check out the Draper docs for more information. Draper doesn’t have a monopoly on decorators; it just makes them faster to implement with a proven approach.

Separation in a Rails monolith: layouts, assets, and controllers

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:

Booking a reservation on TourExec

Admin has a fuller layout, with a navigation bar:

Admin section of TourExec

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

 

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:

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:

Update your layouts to use each manifest

Our admin layout uses:

Our public layout uses:

 

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.

Consider Turbolinks 5 for your next Rails project

Turbolinks 5 is a library for web applications that makes pages load faster. Here’s how:

  • When the user navigates, it replaces only the body of the page (and merges the headers) with AJAX, instead of doing a full page load
  • If the user navigates to a page that they’ve already viewed in that session, it displays a cached version and then checks for new content in the background

These features make your app appear at least 2x as fast to the user.

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.

Booking a tour

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.

E-mail in Rails with MailChimp and Mandrill, a comprehensive guide

Intro

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

  1. Add new users to a mailing list
  2. Send a welcome e-mail to new users
  3. 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:

  1. The customer was billed.
  2. A new video was posted to a category that the customer chose to monitor.
  3. A charge to the customer’s credit card failed.

When an action above occurs, we need to notify a particular user – or, as we cover in Advanced Transactional E-mail, multiple users.

Mandrill, from the folks at MailChimp, is a popular tool for sending transactional e-mails. It’s free for apps with low e-mail volumes.

Continue reading E-mail in Rails with MailChimp and Mandrill, a comprehensive guide

MailChimp and Active Job on Rails 4 – adding users to your mailing list in the background

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.

Rails 4.2 offers Active Job, an easy way to define background jobs.

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.

This generates a new job:

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

Finally, in our user class, run the job after a new user is created:

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.

Sitemaps in Rails, in five minutes

Not every web app needs a sitemap, but in certain cases having one can significantly improve your visibility on Google.

For instance, you might have pages that are hard to find, or that you haven’t entirely exposed to the public. You might be a brand new site that wants to get indexed as quickly as possible.

Read over Google’s reasons for having a sitemap. Take it from the authority on the matter, the ultimate “SEO expert.”

If you’re on the fence, go with a sitemap. Google states that “In most cases, webmasters benefit from sitemap submission, and in no case can you be penalized for it.”

Don’t you love the word “webmaster”?

Adding a sitemap to a small-to-medium size Rails app is a breeze. Here’s the how-to:

Step 1. Create a view for your sitemap

Your sitemap is going to be a plain old Rails view, albeit one in XML format. Below are examples in HAML and ERB.

HAML (haml-rails gem required):

A couple of important notes:

  • We’re using the post_url helper, not the post_path helper, because we need absolute URL’s in the sitemap.
  • Obviously, replace post with whatever model(s) holds the stuff you want in the sitemap.
  • If your site heavily features images and videos that you want indexed, add media metadata to your sitemap.

Step 2. Create a controller

The view above uses the @posts variable. It needs to get that from a sitemap controller:

Step 3. Add a route

Step 4. Test it out

This very simple test ensures that the sitemap is basically working, and exists mainly to ensure it doesn’t get broken in the future.

For real sitemap validation, see the next step.

Step 5. Test your sitemap and submit it to Google

Register your site on Google Webmaster Tools.

From there, you can validate and submit your sitemap for crawling.

At the end, you should see a count of the URL’s in your sitemap. You’re done!

Sitemap submission confirmation

Alternatives

The sitemap above is generated on-the-fly as search engines request it. If your site is particularly huge, you could generate the sitemap on a schedule. This certainly complicates things, but there are gems to help: sitemap_generator, for instance. I evaluated these but found they added too much overhead to the deployment and maintenance processes for a medium-size app.

Inspired by this Stack Exchange answer

React JS and Flux in Rails, a complete example

I recently wrote about real-world results with React JS. Here is a concrete example of adding React to a Rails app, start to finish.

React JS is a library from Facebook that powers user interfaces. It is simpler, faster, and less opinionated than many JavaScript MVC frameworks, making it easier to bring into an existing app. Start by reviewing our recommended React resources, then check out an example below.

The example

At Cook Smarts, we want recipes to be consistent, so we provide administrators with suggested ingredient names. That way, a red bell pepper is always called a red bell pepper.

Suggestions are populated from previous recipes automatically, but they need to be pruned by an administrator to make sure they’re accurate.

The app needs to provide an Excel-like way to quickly prune suggestions.

React JS, in under 150 lines of readable code, gets us exactly what we need, an Excel-like data editor.

Editing ingredient suggestions

Tooling

The example below relies upon Ruby on Rails, the react-rails gem (latest stable version), and Fluxxor (added to the app’s JavaScript manifest).

Our server actions in Rails

A Rails controller provides JSON data to the view and processes edits and deletions to the database.

Our data model in Fluxxor

A typical React implementation includes a data model, or store, which manages data and the actions that can be taken on the data. At a Cook Smarts, we use Fluxxor,  inspired by Facebook’s Flux concept.

A JavaScript object holds our store and defines the actions that the store will take (renaming and deleting ingredients):

The object contains the store itself, instantiated through Fluxxor’s createStore method.

The object also contains the store’s actions, which communicates with the simple API we defined in the Rails controller:

Finally, the object includes a method for creating a Flux object containing the store and its actions. The Flux object is passed to the React-based UI in the next section.

Read more about Fluxxor and how it helps you easily define data models that play well with React. For more on the concept, check out Facebook’s Flux overview.

Our UI in React

So far, we have covered the server-side API and the client-side data store. We still need to build our client-side UI, and that’s where React comes in.

React apps are basically component trees. The ingredient suggestions editor contains multiple ingredient suggestions,, so our component tree at its simplest is:

  • IngredientSuggestionsEditor
    • IngredientSuggestion
    • IngredientSuggestion
    • IngredientSuggestion

The IngredientSuggestionsEditor component is the parent, and watches the Flux store for any changes (see code comments):

The component above renders an IngredientSuggestion component for each ingredient. The IngredientSuggestion component shows the name of the ingredient and allows the user to edit it (see code comments):

Tying it all together

All of the code above is in a global JavaScript function that we call from our Rails view.  That function spins everything up and renders the UI to the page. Global functions aren’t ideal, but Rails’ asset pipeline leaves us with few other options. While a bit inelegant, this approach works well in a Rails app.

The global function creates the Fluxxor store and renders React components to the page. Here is its code, excluding the snippets we’ve already covered:

The Rails view containing the suggestion editor runs the global function on page load, passing all the ingredient suggestions in JSON format, which we passed to the view from the Rails controller:

Here’s the full code for the Rails controller, Rails view, Fluxxor store/actions, and React components.

In the future it will only get easier to connect React and Rails, with a new 1.0 version of the React gem in the works. At Cook Smarts, we use the latest stable React gem and include Fluxxor in the app’s JavaScript manifest.

React allowed us to get a client-side interface up and running in a couple of hours.  React presents few surprises and operates consistently. It’s no wonder that it powers much of Facebook and Instagram, two sites that have to work for a wide array of users.

Avoid the N+1 problem in Rails by harnessing your database

The #1 cause of slow apps may be the N+1 problem, where the app queries a database over and over again to get information about a list of items.

To avoid this, learn the powers of your database so you can query it more efficiently.

Say that you have an app to manage meetings. When someone creates a meeting, there is a standard checklist that they must complete.

The standard checklist items, which are the same for every meeting, are stored in the Checklist table. When someone checks off an item for a particular meeting, that action is stored in Checklist Checked Items table.

Here is the database structure and the sample records we’ll use in this example. For the only meeting in the database, the user has completed two of the checklist items.

meetings

  • id: 1, title: A Meeting

checklist_items

  • id: 1, title: Book meeting location
  • id: 2, title: Arrange catering
  • id: 3, title: Invite people

checklist_checked_items

  • id: 1, checklist_item_id: 1, meeting_id: 1
  • id: 2, checklist_item_id: 2, meeting_id: 1

Say you want to retrieve, for a given meeting, the checklist items and whether each has been checked. You want any checked items to appear at the end of the list.

Here is the app-centric way to do that:

  1. Query the checklist items
  2. Loop through the checklist items, and for each, query the checked items to see if it’s been checked for that meeting
  3. Place each of the items, and whether it’s been checked, in an array of hashes
  4. Sort the array of hashes to place checked items last

This is inefficient and presents the N+1 problem, with step 2 producing multiple queries that will only increase in number as your app grows. Furthermore, there is an unnecessary array middleman and a sorting operation on that array.

Here is the database-centric way:

  1. In one query, get the checklist items, whether each is checked, sorted by whether each is checked.

That’s right, one query has replaced many, and the databsae is doing all the work.

The secret lies in Postgres’s CASE function, which lets you insert conditional logic into queries.

Here, we join checklist_items and checklist_checked_items a checked field that shows whether the checklist item is checked for that particular meeting:

Or, using ActiveRecord:

This returns the checklist items and whether they’re checked, with checked items last:

  • title: Arrange catering, checked: false
  • title: Invite people, checked: true
  • title: Book meeting location, checked: true

By understanding Postgres’s CASE function, we were able to replace many queries with one, speeding up our app.

This is just one example of how your database can take the burden and handle it better. Read your database’s documentation to discover more.

Further reading: