Rails 7.1 is finally here, nearly 2 years after 7.0 was released. My initial reaction was that – with a couple notable exceptions (strict locals in ERB views and an auto-loaded lib directory, hooray!) – most of the major features in the release notes were a bit underwhelming.
However, as I dug deeper into the 2,000+ pull requests merged since Rails 7.0, I realized that there are several interesting features and changes, many of which haven’t been widely promoted. Here’s what caught my attention:
- Finally, we can write proper integration tests for errors
- SSL is now on by default in production
picture_taghelper supports responsive images
- Development and test log files no longer grow to infinity
webdriversgem has been removed
- Active Record enums can now validate like other attributes
- Deployments to Linux work out of the box
Before Rails 7.1, if you wanted to write an integration test for an error scenario that returned a 404 status, this would not work:
get method raises
ActiveRecord::RecordNotFound. You may be tempted to set
config.action_dispatch.show_exceptions = true to get this test to pass, but this disables stack traces for legitimate errors.
In Rails 7.1, there is now a clean solution:
Now integration tests will correctly render a 404 response instead of halting with an exception. Other errors that can’t be rescued (i.e. legitimate bugs) will still raise with a stack trace.
For more details, check out this PR: Make the test environment show rescuable exceptions in responses #45867.
It probably goes without saying that we should all be using secure cookies and HTTPS in production. Prior to Rails 7.1, you needed to remember to explicitly set
config.force_ssl = true for this to take effect. Without it, your requests might technically still be traveling over HTTPS (depending on your hosting or CDN setup), but without the full security of HSTS and https-only cookies.
In Rails 7.1,
force_ssl is now on by default in production. If you are deploying to a private staging or hobby environment where a full HTTPS stack is not possible, you can opt-out by setting
config.force_ssl = false.
When developing responsive web apps, sometimes you’ll need to deliver different images to different browsers. Here are a few scenarios:
- For efficiency, you want to deliver a WebP version of an image, but you also need to provide a PNG version as a fallback for older browsers.
- You want to swap between different images based on screen size or orientation.
- You have low-res and hi-res versions of images that are appropriate for different devices based on their screen density.
<picture> tag is designed to solve for these use cases. Rails 7.1 adds nice syntactic sugar for generating them with the new
The resulting HTML:
Rails helpfully writes very detailed logs to
log/test.log. But over the course of months and months of fast paced test-driven development, these files could grow very large. I’ve seen some apps with log files over 1 gigabyte. Before Rails 7.1, there was technically no upper limit.
Rails 7.1 now caps development and test log files at 100 MB. Whew!
webdrivers gem has long been included in the default Rails
Gemfile to facilitate browser testing. If your tests use chromedriver, webdrivers would automatically detect the necessary chromedriver version and download it, so that you didn’t need to install it manually (e.g. via homebrew).
Fast-forward to 2023, and the
selenium-webdriver gem has taken over this responsibility. The webdrivers gem is now deprecated.
In short, as long as you are using Ruby 3.0+, the latest version of
selenium-webdriver has you covered. You can remove
webdrivers from your Gemfile. In Rails 7.1,
rails new no longer includes it.
Prior to Rails 7.1,
enum attributes always raised an exception when assigned invalid values. For programmatically-maintained fields, like an internal state machine, this made sense. However it was not a good fit for user-provided data.
In Rails 7.1, this behavior is now configurable to provide user-friendly validation errors.
To make dependency resolution more predictable, recent versions of Bundler include platform information in the
Gemfile.lock. This means that, for example, a
Gemfile.lock created on macOS will not work on Linux until
bundle install is run in a Linux environment to update the lock file and resolve any Linux-specific dependencies.
That may sound reasonable, but in Rails, it can make for a frustrating experience.
- Many Rails developers are using macOS.
- As a result, the initial
Gemfile.lockgenerated when they run
bundle installwill include macOS platform information, but not Linux.
- Nearly all cloud deployment and CI platforms use Linux.
- Inevitably, the first time a deploy is attempted to Linux, it fails with a Bundler error.
Specifically, Bundler’s error message will instruct you to run this command:
bundle lock --add-platform=x86_64-linux
This is such a common obstacle that Rails 7.1 now includes its own workaround. When you generate an app using
rails new, Rails 7.1 will automatically run the
lock command to make sure the resulting
Gemfile.lock includes Linux support. This ensures the first deploy to a Linux environment will “just work”, even if you develop on Mac.