Enabling Rails 7.0's New Framework Defaults
Tags: rails, ruby, howto, webdev
Published: 2024-05-18 23:48:06

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](https://github.com/rails/rails/blob/main/activesupport/lib/active_support/digest.rb) 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](https://github.com/search?q=repo%3Arails%2Frails%20hexdigest&type=code) 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](https://github.com/rails/rails/pull/42025) 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] (https://github.com/rails/rails/pull/45304) 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
```

## `Rails.application.config.active_support.executor_around_test_case = true`

Looking at this [PR](https://github.com/rails/rails/pull/43734) 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](https://api.rubyonrails.org/classes/ActiveSupport/CurrentAttributes.html) to be reset after each request, even if there are multiple requests within a single test. (the [following](https://github.com/rails/rails/blob/main/railties/test/application/action_controller_test_case_integration_test.rb#L70) 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](https://github.com/rails/rails/blob/7-0-stable/activerecord/CHANGELOG.md)

> 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](https://api.rubyonrails.org/v6.0.2.2/classes/ActionController/Redirecting.html) 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](https://github.com/rails/rails/blob/6-0-stable/railties/lib/rails/generators/rails/app/templates/config/initializers/wrap_parameters.rb.tt). 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](https://api.rubyonrails.org/v6.0.2.2/classes/ActionController/ParamsWrapper.html) 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](https://api.rubyonrails.org/classes/Digest/UUID.html) 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](https://github.com/rails/rails/pull/37682/files)



## `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](https://github.com/rails/rails/pull/41769) 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!!