DEV Community

Cover image for Enabling Rails 7.0's New Framework Defaults
Hassan Ahmed
Hassan Ahmed

Posted on

Enabling Rails 7.0's New Framework Defaults

Recently I had a chance to enable Rails 7's new framework defaults, I thought I'd share the research and reasoning that I was able to extract for each of these via blog post.

Before you proceed:

This is not the complete list of the new Rails 7 defaults, there are a few missing, that I will try and document soon in this same blog.

Also I'd recommend, doing your own research along the way and suggest any improvements/corrections to this post as well.

Lets jump right into the new defaults then!

Rails.application.config.action_view.button_to_generates_button_tag = true

Uncommenting this default would now generate a button tag rather than an input tag of type submit in the from rendered by the button_to helper.

To Uncomment
This should be safe to uncomment if you are not using button_to helper. If you are, ideally test coverage should be in place to detect any unexpected behavior or you can also manually test if its feasible. There may be some slight change in behavior e.g if you are relying on some param being sent to the controller by the button_to helper prior to uncommenting this line.

Rails.application.config.action_view.apply_stylesheet_media_default = false

Uncommenting this line would mean the stylesheet html tags that are rendered by stylesheet_link_tag will no longer include the media attribute set to screen.

To Uncomment
Uncommenting this line would mean, style sheets will be applied to all media types unless you have explicitly specified media attribute on any. For safety you can check all the included stylesheets in your project and determine if you need to make any changes and then uncomment this line.

Rails.application.config.active_support.hash_digest_class = OpenSSL::Digest::SHA256

You may notice in the new_framework_defaults_7_0.rb file mentioning the impact of this change, which is cache invalidation.
In order to gather some more information I looked at the ActiveSupport::Digest which basically has just 3 class methods, a setter & getter for hash_digest_class and the hexdigest method. Furthermore, I searched across the rails/rails repo to find the usage of ActiveSupport#hex_digest_class (if interested this link leads to the search results) to find most of its usage only around code that deals with caching. This included caching of views, active_record queries, http ETAGs and also cache keys for the cache store you have set e.g. redis, filestore etc.

To Uncomment:
Uncommenting this would mean cache keys will now be read/generated using the new SHA::256 digest and existing cache keys will no longer be readable resulting in cache misses across all the impacted areas and resulting in new cache keys being generated using the new digest. This can mean a dip in performance initially for your application. Also, previously generated cache entries using SHA::1 will stay in the cache store you have configured until their expiration which may also mean some additional storage being consumed from your cache store for that time period.

Rails.application.config.active_support.remove_deprecated_time_with_zone_name = true

With this flag commented, ActiveSupport::TimeWithZone.name returned Time rather than the actual class name. Uncommenting this flag will return the actual class name rather than this overridden implementation.

To Uncomment
If you are not using ActiveSupport::TimeWithZone.name anywhere in your codebase, this should be safe to uncomment. If you are, you may have to handle those cases accordingly or disable this default in the application.rb, whatever works for your case.

Rails.application.config.active_support.cache_format_version = 7.0

Rails 7 introduces a more optimized serialization format for caching. This new format should be able to read cache entries that were serialized with Rails 6.1 but, Rails 6.1 will not be able to read the entries serialized using this new format so only enable this flag after you don't plan to move back to using a previous Rails version.
Refer to this pull request if you are interested in knowing more details about the implementation.

To Uncomment
As long as you have no plans to move back to Rails 6.1, you can safely enable this flag, as mentioned, cache entries serialized by 6.1 should be read by the new format as well.

Update
It seems to enable this flag, you need to set it in application.rb (pull request for reference) as later an issue was raised highlighting that merely uncommenting this flag did not make the app use the newer cache format. You can verify yourself as well the behaviour in console by using

Rails.cache.instance_variable_get(:@coder) 
# and check whether the returned value is ActiveSupport::Cache::Coders::Rails70Coder or ActiveSupport::Cache::Coders::Rails61Coder
Enter fullscreen mode Exit fullscreen mode

Rails.application.config.active_support.executor_around_test_case = true

Looking at this PR to extract more details around this default, it looks like it should be relatively safe to uncomment it. This will allow data like Current Attributes to be reset after each request, even if there are multiple requests within a single test. (the following test case also gives some idea).

To Uncomment
If the build is green then it shouldn't be much of an issue in my opinion.

Rails.application.config.active_support.isolation_level = :thread

Quoting the comment next to this default

If you use a fiber based server or job processor, you should set it to :fiber.
Otherwise the default of :thread if preferable.

This description seems pretty clear in terms of what value should be set. In case you are using a thread based server like puma and a thread based job processor like Sidekiq you can uncomment this default.

Rails.application.config.action_mailer.smtp_timeout = 5

Sets the default timeout value for SMTP requests so that unfulfilled requests are timedout.

To Uncomment
I don't anticipate any regression coming out of uncommenting this default, the way I enabled this was to test some emails on a staging environments and all seemed to work and then closely monitor the bug tracking system of any timeouts.

Rails.application.config.active_record.verify_foreign_keys_for_fixtures = true

Quoting the changelog entry from rails 7 stable version

Tests will not run if there is a foreign key constraint violation in your fixture data.
The feature is supported by SQLite and PostgreSQL, other adapters can also add support for it.

To Uncomment
If you are not using fixtures for your specs, this might have no impact at all for you. If you are, uncommenting this should raise the foreign key violations that you will have to fix.

Rails.application.config.action_controller.raise_on_open_redirects = true

To prevent open redirect attacks, uncommenting this default will raise an error whenever redirect_to or redirect_back redirects to a different host.

To Uncomment
In my opinion having a good test coverage is important for this one, once uncommented (if there is proper test coverage), it should be able to highlight the areas from where external redirection is taking place. If its necessary to keep the redirection you can permit it by using allow_other_host option in those places. You can also search your codebase for redirect_to or redirect_back to see whether at any of those places you are redirecting to an external host.

Rails.application.config.action_controller.wrap_parameters_by_default = true

Your Rails application may have an initializer by the name of wrap_parameters.rb with similar content. The purpose of this functionality is to wrap parameters sent to a controller in a nested hash. For example and further reading please refer to this page from docs (v6).

To Uncomment
If you haven't made any changes to the wrap_parameters initializer, this default is safe to uncomment, otherwise you can keep on using the customized version of your initializer and disable this default in application.rb.

Rails.application.config.active_support.use_rfc4122_namespaced_uuids = true

Can safely be uncommented if you are not using any of the methods from Digest::UUID in your codebase.

From what I could gather after going through the changes in the mentioned PR (below), it fixes behavior of generating UUIDs when provided namespace is different from the ones defined in the class.

Reference PR

Rails.application.config.action_dispatch.default_headers

This default changes the X-XSS-Protection response header's value to 0 which means disabling it in favor of CSP (Content Security Policy). It seems almost all major browser no longer support this header due to some of the vulnerabilities it came with.

PR for more details.

To Uncomment
Its always good to have an effective CSP for your application, I'd recommend to create one if you haven't for your app before uncommenting this default.

Thanks for reading, if you have some feedback or want to suggest some correction, please feel free to share those in the comments below.

Programming bliss to you!!

Top comments (0)