August 22, 2019

New framework defaults in Rails 6

Rails 6 is released. This post is part of the Road to Rails 6 series which will prepare you for Rails 6.

Every time a new major Rails version is released, there are tons of breaking changes. Upgrading existing app to the new version can be sure shot recipe for breaking certain pieces of code due to these changes. But starting from Rails 5, Rails makes adopting the big-bang reforms a bit easier with the help of a file called new_framework_defaults.rb

new_framework_defaults file is created when you run the rails app:update task after updating the Gemfile to use Rails 6. It is not created if you don't run the update task. Running the update task is extremely important as it updates some other configurations as well.

For every new major Rails version, a separate file is created for the framework defaults. For Rails 5.2 it is new_framework_defaults_5_2.rb. For Rails 6 it is new_framework_defaults_6_0.rb. If you upgrade your app to Rails 6, you will find new_framework_defaults_6_0.rb under config/initializers.

This file helps in adopting these breaking features at your pace based on the complexity of your codebase. If you open this file, you will find that everything inside it is just commented out.

# Don't force requests from old versions of IE to be UTF-8 encoded.
# Rails.application.config.action_view.default_enforce_utf8 = false
...
# Enable the same cache key to be reused when the object being cached of type
# `ActiveRecord::Relation` changes by moving the volatile information (max updated at and count)
# of the relation's cache key into the cache version to support recycling cache key.
# Rails.application.config.active_record.collection_cache_versioning = true

Confused? Worry not. In this post, we will go over the contents of this file and see how to adopt these features in your application.

If you are creating a brand new Rails 6 application, then this file is not created. Because Rails makes sure that all the major breaking features are enabled by default.

Feature flags

Every new major breaking change is hidden behind a feature flag most of the times. This makes it easy to adopt a feature after making sure that your application code is changed as per the breaking change. For eg. let's take an example of collection caching improvements in Rails 6. Rails 6 makes it possible to reuse the cache key of the ActiveRecord::Relation objects by moving the changing part of the cache key such as the updated timestamp and count into cache version. This change is controlled by Rails.application.config.active_record.collection_cache_versioning.

Rails calls these feature flags as framework defaults and puts all of them in the new_framework_defaults_6_0.rb file.

For new Rails 6 apps, this change is enabled by default and the configuration is set to true.

For old apps being upgraded to Rails 6, this setting is set to nil and a line is provided in new_framework_defaults_6_0.rb to enable it when you want to start using this feature.

# new_framework_defaults_6_0.rb

# Enable the same cache key to be reused when the object being cached of type
# `ActiveRecord::Relation` changes by moving the volatile information (max updated at and count)
# of the relation's cache key into the cache version to support recycling cache key.
# Rails.application.config.active_record.collection_cache_versioning = true

Now you will appreciate why all the lines are commented in the new_framework_defaults_6_0.rb. Rails expects that you will enable the new defaults carefully after looking at the impact that change has on your code.

Embracing all the new framework defaults

You are ready to use all the new framework defaults, well then just delete the new_framework_defaults_6_0.rb file and change following line in config/application.rb

# Initialize configuration defaults for originally generated Rails version.
# config.load_defaults 5.2
config.load_defaults 6.0

Originally it is set to load defaults from Rails 5.2 for the app being upgraded to Rails 6. Now we have changed to load the defaults from Rails 6.

For new Rails 6 apps, this setting is already set to load defaults from 6.0.

Adding a new default configuration

If you are adding a breaking change to Rails then how should you go about it in adding to new_framework_defaults?

Take the help of Rails contributors who will review your code. They will guide you in the right direction about adding proper default value for old apps in the new_framwork_defaults.

The structure of new framework defaults makes it easy for Rails team to introduce breaking changes which are necessary without compromising the ease of the upgrade process for old apps.

Want to stay on the Road to Rails 6?

Subscribe to my newsletter and get a weekly email to know more about how to make your app ready for Rails 6.