Upgrading to Rails 5.1 + 5.2

Climbing stairs to Rails 5.1

Rails 5.1 shifts everything around in terms of Javascript and front-end. After years of infighting, the Rails core team adopts what had become widespread for the Javascript community. Many, many new things are introduced in Rails 5.1 and 5.2, including this new paradigm for Javscript and CSS packaging. This largely opens the door for Rails to play nicely with the NPM ecosystem: React, ViewJS, Ember, Angular, Ionic, etc. The Rails attitude on the Rails vs. NPM debate becomes “both/and” instead of “either/or.”

But to get there, let’s take a quick look at Yarn and Webpacker.

As always, pay attention to your deprecation warnings in Rails 5.0. That’s the warning output that you see in your Rails log when you are working with your app. Fix those first on Rails 5.0 before switching your Gemfile to 5.1.

UPGRADING TO RAILS 5.1

A LOOK AT GITIGNORE

It’s not the most sexy thing, btu let’s take a look at the defualt .gitignore file. Rememer, this is the file that tells Git what not to incldue in your repository.

/log/*
/tmp/*
!/log/.keep
!/tmp/.keep

/node_modules
/yarn-error.log

.byebug_history

We never include the /log or /tmp, that makes sense, but notice that we also are ignoring /node_modules and /yarn-error.log.

YARN

Meet Yarn. Yarn is a package manager. It’s a lot like bundler, but it is Node (which means you are running Javascript). Yarn supports a number of fancy features, but the most significant thing you’ll need to meet if you’re new to the JS ecosystem is a new file:

package.json

The package.json file is at the root of your product directory and tells Yarn what packages to include.

When you use the Rails new command, (assuming your app name is HelloWorld) the default package.json generated is

{
"name": "HelloWorld",
"private": true,
"dependencies": {}
}

Now, let’s add the popular CSS framework and grid system Boostrap. Type yarn add bootstrap.

You’re gonna see something like this

On the shell prompt I’m going to use a unix command I didn’t even cover, more, which simply shows me the contents of the file immediately in the shell prompt.

I’m going to type more package.json

You’ll notice that bootstrap 4.5.0 was added as a dependency. (When you try it, you will get the latest version of bootstrap available in node package manager, which might not be 4.5.0.)

WELCOME WEBPACK

You are softly invited, not required, to use Webpack. It is an alternative to the Sprockets for delivering your assets (Javascript, CSS, images) through to the user. Webpack is based on Node and works a bit faster than Sprockets. As well, in development it compiles nearly instantaneously. Prior to this, Sprockets required you to stop your app & reload your development server when you made Javascript changes. For this reason, it becomes widely preferred. However, it is not mandatory— you can still use Sprockets with Rails 5.1 and 5.2.

To continue installing Boostrap, add this to app/assets/stylesheets/application.css

*= require bootstrap/dist/css/bootstrap

IMPORTANT: If you use SCSS, you should DELETE the application.scss file if you have it. The correct syntax for SCSS is to add to your file app/assets/stylesheets/application.scss)

@import 'bootstrap';

Then to app/assets/javascripts/application.js, add

//= require bootstrap/dist/js/bootstrap

BYE BYE JQUERY

Jquery is no longer installed by the default Gemfile. This does not affect you if you are upgrading from an existing pre Rails-5.1 app.

Let’s say you need jQuery. Here you go:

Add jQuery To A Rails 5.1+ App with Yarn/Webpack

Add jquery to your package.json via yarn. Run this on your command line:

yarn add jquery

Go to config/webpack/environment.js and add this code in between the existing two lines

const webpack = require('webpack')
environment.plugins.prepend('Provide',
  new webpack.ProvidePlugin({
    $: 'jquery/src/jquery',
    jQuery: 'jquery/src/jquery'
  })
)

The complete environment.js file looks like so (the part you are adding is shown in red.)

const { environment } = require('@rails/webpacker')

const webpack = require('webpack')
environment.plugins.prepend('Provide',
  new webpack.ProvidePlugin({
    $: 'jquery/src/jquery',
    jQuery: 'jquery/src/jquery'
  })
)

module.exports = environment

Add require("jquery") to your application.js file so it looks like

require("@rails/ujs").start()
require("turbolinks").start()
require("@rails/activestorage").start()
require("channels")
require("jquery")

SYSTEM TESTS

Essentially, Capybara now comes by defualt, which is great because you should be using Capybara. The new in-vogue term is “system test.” The idea is flex (or put through its paces) your system: load front end content, interact with the forms via Capybara, and test that the whole system works end-to-end.

System tests being default brings a coalence around a generalist strategy for Rails— and a good idea for the generalist Rails developer to adopt: What you should be testing are units (unit testing) and system tests (previsouly kwown as “integration testing” or “integration specs”). What the community once thought of as Controller testing, and the idea of Unit-Controller-Integration testing being similar to Model-View-Controller, is now a relic of the past. Focus on Unit testing your models and System testing your whole system.

If you really, really feel that controller spec are approrpiate for your app (and I’d recommend them only in special cases), the previous Rails controller testing functionaliy has been extracted into a gem rails-controller-testing.

What the community once thought of as Controller testing, and the idea of Unit-Controller-Integration testing being similar to Model-View-Controller, is now a relic of the past.

—THE RAILS COACH

ENCRYPTED SECRETS

You may remeber back in Rails 4.1 that the config/secrets.yml file was introduced. Now, inspired by a gem called sekrets, the encryption goes to a new level. Before continuing, note that in Rails 5.1 it is designed for Production only. For this reason, I don’t recommend the 5.1 implementation and I will cover how to set it up withn it is support for multiple environments.

In short, the credentials to your necessary external services (API keys) are stored encryted in source control (that, is Git or Github). However, do not keep the master key in source control. This is very important. Only the production environment has the master key, and you probabl y shouldn’t even store it on your own laptop or give it to developers working for you. In other words, the master key unlocks all of the application’s necessary API keys.

You have two choices for where to store the master key:

  1. In an environment variable called RAILS_MASTER_KEY
  2. in the config/secrets.yml.key file. (Remember, you don’t check this file into Git so be sure it is in .gitignore)

I am just introducing you to these concepts here, we won’t start using this until full environment support is available in a future version of Rails.

PARAMETERIZED MAILERS

form_with

Although form_with was not introduced in this version of Rails, it was unified with form_for and form_tag, which means its syntax is the same. Form_with is now the preferred syntax, so if you still have the old syntax switch it to the new form_with.

UPGRADING TO RAILS 5.2

Rails 5.2’s has one big feature and five minor ones:

Active Storage

ActiveStorage is a replacement for Paperclip, a popular gem that used to let you add image and media (sound clip or documents) to your Rails app. You can do it with ActiveStore very easily, and under the hood ActiveStorage provides many of the things Paperclip provided: automatic resizing, image process, etc. This is a great way to build a part of your site where users can upload media like JPG, PNG, audio files, CSV files, etc.

Redis Cache Store

Rails 5.2 ships with built-in Redis cache store. That means that you should run Redis as the defualt.

HTTP/2 Early Hints

Basically what we have here is an experimental standard introduced by the Internet standards organization called “Early hints” that relys on HTTP/2. HTTP/2 is different in that it is able to communicate between client & server more fluidly, and keep connections open for server-to-client communication. In this example, the idea is that as the web server you can send down and “early hint” to the user of what might happen for them when the full page is responded to. The Early Hints RFC is here. After having read through it, the RFC provides little concrete examples of what application this has other than to say the hints could be in the form of headers. For example, to let the user know the sever found the resource and the request is processing. I guess in a real-time app this could give users a sense of confidence.

To start your sever with early hints

rails server --early-hints

Credentials

As discussed above, the secret key is probably stored in config/secrets.yml.enc. However, with Rails 5.2, you can now start storing these in config/credentials.yml.enc. However, because it still doesn’t support multi-environment setup, I still don’t recommend using it in Rails 5.2 (environment-specific credentials aren’t added until Rails 6.)

Content Security Policy

This is an advanced feature involving multi-tenant applications — that is, applications which host other applications. You can use Content Security Policy to restrict the set of Ruby commands a guest application has access to on the host for security.

I hope you’ve enjoyed this quick tour of Rails 5.1 and 5.2. In many ways, these changes are some of the most signfiicant Rails has seen years.

Please be sure to like and follow (below) for more.