On October 5th, Rails 7.1 has been released. In this article, I will show you how I upgraded one of our projects, OneTribe ( ), to the new major release within one day of my holidays. https://onetribe.team/ Prerequisites OneTribe runs Ruby 3.2.2 and Rails 7.0.7. We host on GitHub and deploy with GitHub Actions and Kamal. code Dependencies Update I started with upgrading rails in the application Gemfile. # Gemfile gem 'pg_party' # ... gem 'rails', '~> 7.1.0' gem 'rails-i18n' After this, you can try to run and depending on your other dependencies, it will either succeed or fail. In my case, it failed because does not support Rails 7.1 yet. bundle update rails pg_party The good news is that Ryan (author and maintainer of PgParty), with help from me and one more developer, within one evening, but didn’t release the new version of the gem yet, so I am going to take the code from the branch. managed to add support for AR 7.1 main # Gemfile gem 'pg_party', github: 'rkrage/pg_party' After solving the issue with the PgParty bundle, it succeeded. I was almost sure that the application was ready for the next phase of the update, but I remembered that Rails 7.1 introduced composite primary keys for ActiveRecord support out of the box (you can find a full list of new features and improvements here: ). https://rubyonrails.org/2023/10/5/Rails-7-1-0-has-been-released In OneTribe, we’ve used the gem called ( ). It was rather easy; I replaced call with and removed from the application bundle. composite_primary_keys https://github.com/composite-primary-keys/composite_primary_keys self.primary_keys = <array> self.primary_key = <array> composite_primary_keys class TimeTracking::Entry < TimeTrackingRecord # with composite_primary_keys # self.primary_keys = :id, :date # with ActiveRecord 7.1 self.primary_key = [:id, :date] range_partition_by :date # ... end After this, I updated Sidekiq to 6.5.11, , and tried to start the application. However, I got an error. which added support to Rails 7.1 ActionText in Rails 7.1 introduced a new HTML 5 sanitizer, which is now default and falls back to HTML 4. As a result of this change, and are applied at runtime and return nil during application load. ActionText::ContentHelper.allowed_tags .allowed_attributes In our case, I don’t need additional tags to be added to ActionText allowed tags configuration, and I removed the initializer. I ran the application test suit, and all specs passed successfully, meaning I can start . rails app:update Application Configuration Update Rails has a special task that can help you to update application configuration in an interactive mode. I used VS Code for development and wanted to use its merge tool, so I specified the THOR_MERGE constant before running the command and used the merge tool to track changes over files. rails app:update THOR_MERGE="code --wait" ./bin/rails app:update One notable change in the 7.1 release is that option with that has an inverted meaning. Both options will still work for backward compatibility, but I suggest to replace with in environments configuration files. config.cache_classes has been replaced config.enable_reloading config.cache_classes = false config.enable_reloading = true Another new configuration option of Rails 7.1 is . I always try to reduce the number of callbacks used in controllers since they can be extremely hard to maintain. However, there may be situations when controller callbacks fit well (e.g., authorization check). Conditional callbacks are an even bigger hell. Before Rails 7.1, if you defined a condition with or option for an action that does not exist, Rails would say nothing. Now, you can set for test and development environments, and Rails will raise an exception. You can read more info in the railties changelog: . config.action_controller.raise_on_missing_callback_actions only except config.action_controller.raise_on_missing_callback_actions=true https://github.com/rails/rails/blob/7-1-stable/railties/CHANGELOG.md In my Kamal guide, I showed how to create an initializer, which will deal with a load balancer that terminates SSL (e.g., AWS ALB). Rails 7.1 introduced option. This means that in environments that work behind a load balancer (usually production, staging, etc.), you have to enable it and delete the initializer that you used in Rails 7.0. config.assume_ssl=true # config/environments/production.rb # Assume all access to the app is happening through a SSL-terminating reverse proxy. # Can be used together with config.force_ssl for Strict-Transport-Security and secure cookies. config.assume_ssl = true # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies. config.force_ssl = false After you merge all your configuration files and the interactive tool is finished, some tweaks can still be done. First of all, you may notice that you will have a new file in your code base called . It contains all Rails 7.1 default params commented, so you can enable them one by one. Another option is to change in file to have value and delete , this will enable all options at once. new_framework_defaults_7_1.rb config.load_defaults config/application.rb 7.1 new_framework_defaults_7_1.rb Last but not least is option. Before 7.1, you probably had something similar to the code below in your application that uses Zeitwerk. config.autoload_lib # config/application.rb module OneTribe class Application < Rails::Application config.eager_load_paths << config.root.join("lib") Rails.autoloaders.main.ignore( config.root.join("lib").join("assets"), config.root.join("lib").join("tasks"), config.root.join("lib").join("middleware"), ) # ... end end The code above added folder to both eager load and autoload paths and excluded from autoload paths from lib that didn’t contain or should not be reloaded or eager-loaded. lib Ruby code With Rails 7.1 and , everything becomes easier. You just tell Rails to autoload everything in and provide a list of folders that should not be reloaded and eager-loaded. config.autoload_lib lib # config/application.rb module OneTribe class Application < Rails::Application # Please, add to the `ignore` list any other `lib` subdirectories that do # not contain `.rb` files, or that should not be reloaded or eager loaded. # Common ones are `templates`, `generators`, or `middleware`, for example. config.autoload_lib(ignore: %w[assets tasks middleware]) # ... end end Thats all. I reran my specs to ensure I didn’t break anything. Of course, I ran Rubocop to ensure all the changes fit the code style, created PR, and successfully upgraded OneTribe to the new Rails version. Conclusions Rails 7.1 gives you many new features and abilities ( ), but as usual, the upgrading process is smooth and straightforward. https://rubyonrails.org/2023/10/5/Rails-7-1-0-has-been-released Thanks to all the contributors, the core team, and those who tested the release candidate and beta builds! Also published . here