Rails Upgrades

Summarized using AI

An Upgrade Handbook to Rails 8

Jenny Shen • September 26, 2024 • Toronto, Canada

In her talk at Rails World 2024, Jenny Shen addresses the crucial process of upgrading Ruby on Rails applications to version 8. She begins by drawing a parallel between poorly maintained public transport and Rails app upgrades to emphasize the importance of staying current with framework updates.

Key Points Discussed:
- Introduction: Jenny emphasizes her experience with the issues of outdated public transit, likening this to the risks of neglecting Rails upgrades.
- Prerequisites for Upgrading: Stressing the importance of having tests in place before initiating an upgrade to catch potential issues with production.
- Step-by-Step Upgrade Process: Jenny outlines the comprehensive steps for upgrading Rails apps, including moving to the latest patch version in increments, running update tasks, and reviewing deprecated features.
- Commands to Use: The commands such as bundle update and bin rails app:update are highlighted as essential for this process.
- Benefits of Upgrading: Upgrading Rails not only improves app performance and security but also enhances developer experience while preventing costly rewrites in the future.
- Real-world Example from Shopify: Jenny shares how Shopify handles mass upgrades across their multitude of applications, including maintaining a unified upgrade calendar and creating an internal gem called 'rails-upgrade' to streamline the upgrade process for developers.
- Common Issues in Upgrades: She mentions typical challenges developers may face, such as deprecations in Rails 7.2 that will impact apps during upgrade, addressing legacy issues with commands and queue adapter configurations, and the overall need for developers to adapt to new practices and frameworks efficiently.

Conclusions and Takeaways:
- Strategic Importance: Regular upgrades prevent a fragile infrastructure that can lead to significant user dissatisfaction, similar to the analogy of a city relying on outdated public transportation.
- Proactive Maintenance Strategy: Just as efficient rail systems manage ongoing upgrades, so too should development practices in maintaining Rails apps.
- Community Support: By leveraging internal tools and calendars for upgrades, development teams can improve the Rails upgrading process significantly, creating a smoother transition and better app reliability.

An Upgrade Handbook to Rails 8
Jenny Shen • September 26, 2024 • Toronto, Canada

Rails 8 is here, and in her talk at #RailsWorld, Jenny Shen explores how to get your Rails app upgraded to the latest version in no time! Have too many applications to upgrade? She will also share how Shopify was able to automate the Rails upgrade process for hundreds of their applications.

#Rails #Rails8 #rubyonrails #upgrade

Thank you Shopify for sponsoring the editing and post-production of these videos. Check out insights from the Engineering team at: https://shopify.engineering/

Stay tuned: all 2024 Rails World videos will be subtitled in Japanese and Brazilian Portuguese soon thanks to our sponsor Happy Scribe, a transcription service built on Rails. https://www.happyscribe.com/

Rails World 2024

00:00:07.359 Well, hello everyone and welcome to my talk on an upgrade handbook to Rails 8. I’m glad to be here in Toronto, the largest city in the True North with almost three million people. This population doesn't even include the greater Toronto area. As you can see, this means there are a lot of people who need to get to many different places—over 600,000 rides on the Toronto subway (TTC) occur on an average day.
00:00:16.199 You may have enjoyed a ride on these subways while in Toronto. We have three subway lines, which date back to the 1950s, but many people in the city, including myself, aren't very satisfied with the service. On average, the TTC records around 20,000 subway delays annually. That amounts to over 50 delays each day, with only 14% of transit rides considered on time. You're likely to be late almost everywhere. So why is the TTC so awful? Hold on to that thought; we’ll come back to this. We're here to talk about Ruby on Rails, not the Toronto rails.
00:01:11.680 Before we get into that, let me introduce myself. I'm Jenny, one of the three million people who live in Toronto, and I have plenty of experience with subway closures and delays. I work at Shopify on the Rails infrastructure team. Shopify is a city sponsor, and a couple of us are here, so don't be afraid to say hi! We're also hosting the closing party at our office, so I hope you are hyped for that.
00:02:22.800 Speaking of hype, we'll cover exciting topics about Ruby and Rails upgrades. We'll touch on how to upgrade Rails in an application and its benefits. We're going to upgrade an app to the latest release, and I’ll also talk about how Shopify manages mass upgrades of Rails across the company.
00:02:44.560 Here’s the QR code for the slides if you want to follow along, but they'll be available at the end of the talk. So, how does someone upgrade Rails in an application? The Rails guide gives a great overview of how to upgrade a Rails app to the next minor version. I'll be doing a quick walkthrough for those who might not be as familiar. There are some prerequisites before starting to upgrade Rails.
00:03:09.519 The first is that you need tests in place to prevent unexpected issues from going into production. Tests are the first line of defense, indicating what parts of the app may need changing due to changes in Rails. Make sure you meet the minimum Ruby version required for Rails 8, which is 3.1. The first step in the actual process is to move to the latest patch version after your current version. So, if you're on Rails 7.1.0, you will want to update to 7.1.4. You can do this by editing the version in your app's Gemfile and running 'bundle update.' After that, you'll need to fix your tests and address any deprecated features.
00:04:30.439 Next, move to the latest patch version of the next minor version by running 'bundle update' again. If you're on Rails 7.1.4, you would want to move to 7.2.1. It seems pretty straightforward so far, but there's more. When you upgrade to a new major or minor version, you'll need to run the update task with 'bin rails app:update.' This command helps create new files and modifies old files in an interactive session to reflect the new templates and defaults.
00:05:38.239 You may need to take some time to review the differences between overwritten files to decide which changes should be kept for your app. Lastly, you’ll want to configure framework defaults. One of the files produced by the update task is the new framework defaults file. This includes many commented-out configurations, which you need to uncomment to ensure they work in your app. Once everything is uncommented, you can update the defaults to the latest minor version.
00:06:32.560 To summarize the steps: it’s not the simplest process, and it can take quite a bit of time if there are a lot of broken tests or deprecations. So why do we even bother to upgrade? If you're on Rails 7, let's revisit why the TTC is so awful. One reason for the delays is the reduced speed zones that arise from neglected maintenance, requiring track repairs that can make it unsafe to go at a normal speed.
00:07:05.840 Additionally, the busiest streetcar line in the city is closed from June this year until the end of the year for track and electrical upgrades. The replacement buses are much slower, especially during rush hour. The TTC tends to rely on big repair and upgrade projects only when absolutely necessary, which results in more user dissatisfaction due to these projects impacting the already poor rider experience. So, what does better look like?
00:08:00.200 In Japan, they are known for their efficient and reliable railways because they perform maintenance and upgrades daily at night, keeping service on time and avoiding long periods of closure. To be a first-class city, a city's infrastructure needs to be first-class. First-class cities attract people, and they tend to be happier because they can navigate the city quickly. Fast transit systems are similar to Rails apps; if you don't upgrade Rails in your app and your version becomes end-of-life, you're not receiving backports of security and bug fixes. This ultimately jeopardizes the safety and currency of your application.
00:08:40.760 It might seem easier in the short term to rely on monkey patches or create solutions to fix these bugs, but eventually, apps are forced to migrate for one reason or another. An app running on Rails 3.2 could become unsupported, leading to prolonged outages and further issues, similar to what we see with poorly maintained systems. Like previous releases, Rails 8 is going to be super exciting, with many new features that continue to enhance the Rails experience. This includes support for modern setups, such as the new default behavior in Rails.
00:09:43.440 So, why should you keep your Rails version up to date? To avoid being the 'TTC of Rails apps.' Keeping your Rails apps safe and reliable not only helps prevent costly large upgrades but also promotes a first-class developer experience. Now that we know how to do Rails upgrades and why they are important, I’m going to share some things you may encounter while upgrading to Rails 8. Rails 8 has either been released or is releasing soon; many of the features were also introduced in Rails 7.2.
00:10:36.400 This includes default Progressive Web Application files, dev container configuration, and RuboCop rules, among many others. Be aware that the deprecations in 7.2 will raise warnings and will be removed in Rails 8. So, what applications will be affected? What should you expect to be removed? To illustrate this, we're going to upgrade an application from 7.1 and see what you might encounter.
00:11:07.720 I created an app that tracks TTC service alerts; it scrapes the TTC alerts on Mastodon, allowing you to view posts in the app. You can sort these posts by events and see their resolved status. On the dashboard, you can see ongoing alerts along with the current weather, helping you decide whether to take the TTC or request an Uber.
00:11:54.640 The app is on Rails 7.1.4, and when we upgrade to the next minor version, there will be some deprecations and changes to contend with. As we run the tests, you may encounter issues related to extending your Rails console. To demonstrate this, I created a 'Feeling Lucky' command that you’ll never forget.
00:12:41.760 [Plays song "Never Gonna Give You Up"] This command is great for when you want to feel lucky! However, in Rails 7.2, extending the Rails console through traditional means is now deprecated. This change occurred because IRB introduced an official API for extending the console, allowing you to create helper methods and commands without hacking into the internal parts of IRB. If you want to do an operation that returns a Ruby object, you should use a helper method. For non-Ruby related operations, such as utility functions and displaying information, you should implement a command.
00:13:59.239 For my 'Feeling Lucky' operation, you can define an IRB command with a category description and an execute method, then register it to your console. Rails now recommends using this API, and some of your required files may also be deprecated if they are not updated according to these conventions.
00:15:14.120 Another change in 7.2 involves the Active Job queue adapter configuration. Previously, if you set a queue adapter, it would be used in some tests, but in integration tests with Action Mailer and Active Job, it would still use the test adapter. This could lead to unexpected behavior if you were expecting the application adapter in all your tests.
00:15:44.320 Now, in 7.2, the adapter is consistent across all tests, which may break tests that were built on the previous behavior. If a test using a specific queue fails, you can set the adapter to 'test' in the test configuration to easily resolve this inconsistency. Additionally, Rails will now notify you if a test does not have an assertion. This is crucial, as not having assertions can indicate if a test is broken.
00:16:49.040 Sometimes, you might have a test to ensure an operation doesn't produce an error. You can wrap your assertions in a zero-expectation to demonstrate this intent. For example, if you're testing a resolved event record, the resolution record associated with it should be checked to ensure it exists.
00:17:14.520 In Rails 7.2, there's been a change regarding enum syntax. The preferred syntax now favors positional arguments over keyword arguments, which helps prevent errors due to misunderstanding parameter names.
00:17:23.839 Finally, regarding Rails Secrets, which have been outdated since Rails 5.2, this is a significant change. You should migrate to using Credentials to manage your secrets and avoid the deprecated methods. This is the perfect time to transition to ensure you are following current best practices.
00:18:35.759 Now that we have discussed some plausible changes and deprecations you may encounter, I want to mention some notable file changes that occur when you run the update command. The upgrade command suggests configuring Puma Dev, which is the preferred method for developing multiple Rails apps locally. The default Puma threads have changed from 5 to 3 based on discussions and tests, achieving a good balance between throughput and latency.
00:19:38.680 Moreover, Rails now provides a public view for unsupported browsers, allowing you to specify which browsers your Rails app supports using 'allowed browser' configurations in your application controller. It's important to note these adjustments as they contribute to the overall performance and user experience of your applications.
00:20:18.840 Let’s explore some notable framework defaults. When running the Rails update command, one new configuration to ensure jobs are enqueued after a transaction commit addresses a common mistake in Active Job. Previously, enqueuing jobs from within a transaction could lead to abnormal errors if the transaction failed. However, Active Job will now correctly queue the job after the transaction is confirmed.
00:21:37.559 Additionally, 'wet' is now enabled by default. Wet is Ruby's JIT compiler that has been available since Ruby 3.1, significantly improving latency. These are some updates you could expect during your upgrade journey.
00:22:39.560 Now, I will discuss how Shopify keeps up with Rails upgrades across the company. At Shopify, we have hundreds of Rails apps outside of our core monolith. This includes both internal apps and merchant-facing apps, like an app that allows merchants to sell bundles instead of individual products. Notably, these are standalone apps, not microservices. A few years ago, we faced 20 different Rails versions running across 500 applications.
00:23:56.719 Having so many versions complicates the process of estimating upgrades and managing security issues stemming from older releases. There were little to no expectations for apps to update regularly. Consequently, developers struggled to upgrade their apps, often resorting to simply running a 'bundle update' without truly migrating defaults, which made for a painful process.
00:25:21.439 So, we identified two key areas for improvement: how to maintain our apps up to date and how to make Rails upgrades easier for developers. To tackle the first concern, we introduced an upgrade calendar for Ruby and Rails updates. This calendar allows us to expect apps to run on the latest minor version each year. For apps that fail to meet these expectations, we initiate a deletion process or create an upgrade plan.
00:26:29.200 This eliminates ambiguity regarding when to upgrade and helps teams allocate resources effectively. It also prompts teams to assess their applications' ongoing usefulness, and if they decide an app is no longer impactful, they can initiate an archival process.
00:27:28.560 Regarding easing the upgrade process for developers, we created an internal gem called 'rails-upgrade.' This gem automates the steps outlined in the Rails upgrade guide, allowing developers to run 'rails upgrade' after installing the gem. It identifies the necessary actions for upgrading your app, makes the changes, and provides any required context or follow-ups before the changes should be merged.
00:28:00.840 The gem checks each step outlined in the Rails upgrade guide and has methods to determine whether a step was completed. If not, it executes the necessary changes and commits them to the repository. The upgrade process for the latest patch step checks the version in the Gemfile lock against the patch version, updating accordingly.
00:28:49.680 This process is streamlined, ensuring that the transition is smooth and efficient.
00:28:52.840 The upgrade journey is framed within a context of support and automation to simplify developers' workloads and accelerate necessary updates across Shopify's Rails applications.
00:29:14.080 I’d like to thank everyone who helped make Rails upgrades better at Shopify, and those who assisted me with this talk. If you have any questions or would like to discuss further, here is how you can contact me. Feel free to come up and chat. Thank you!
Explore all talks recorded at Rails World 2024
+13