Unless it becomes a bottleneck, most companies and startups don’t make it a priority to keep their apps up to date. They have their reasons: new features, customer support, scaling, etc.
But they always reach a point where the upgrade becomes imminent and at that point it becomes a massive pain that costs them months and a lot of resources.
I recently upgraded an app from Rails 3 to 6, in 2022 and the company asked me to because Heroku stopped supporting it and they had to implement new features that required the latest versions of some libraries. It was really big and took a while because the code base was big which means delay in implementing and releasing new features.
The same thing happened at one of my previous companies where for 3 years of my service we never chose to stay up to date with the latest versions of ruby & rails and when the time came we took over 3 months to update all of our services.
You should regularly update your code whenever a new version of Ruby or Rails arrives to avoid the mess and cost of upgrading the code base.
Based on my experience and learning from the experience of other developers, I’ve compiled a list of recommendations that companies should follow for a smooth and less time-consuming upgrade.
For me, testing coverage is the most important thing to update your code while making sure it works. Since Ruby is a dynamically typed language, you won’t get any errors until you run this piece of code, which means you won’t know where your code is broken and thus failures, the loss of customers and loss of revenue.
- You should use a single-cov gem to ensure a certain percentage of code coverage to ensure you know when and where the code is breaking.
- You should also add it to the CI pipeline to ensure that your code will never go live if it does not reach a certain coverage percentage.
We must remember that every gem we use is not free. They come with a price which is maintenance. It’s easy if you have 20 or 30 gems but imagine a 5 or 10 year old code base you will find hundreds of lines in your Gemfile and once you decide to upgrade it will be a mess from.
To avoid this, here is a list of tips you should follow:
- Only use gems that have good community support. Otherwise, write your code. Otherwise you will have no support for new versions of Ruby or Rails and therefore technical debt, dependency conflicts between gems, etc.
- Upgrade gems whenever a new version is available. To check which gems are outdated and have newer versions, you can use the following command: obsolete batch
- Drop the version constraints into your Gemfile. You should never specify versions unless it is very critical. Here is a very good article by Clay Shentrup explaining why version constraints should not be used.
- STOP MONKEY PATCHING. You should not use forks for gems in your Gemfile. This would result in an outdated gem that you would have to make downstream changes to sync your fork every time a new version is released and potentially expose you to multiple vulnerabilities.
- Regularly audit your gems for vulnerabilities. There is a gem called bundler-audit that you can use for this purpose. Better include this audit in your pipeline to make sure vulnerable code never goes live
- Delete unused gems: you can use clean beam — dry running command to list all unused gems and then you can delete them.
You should never ignore deprecation warnings. Their purpose is to inform you that this feature or method will no longer be available in the next major/minor release and that you should replace it with the alternative.
This will ease the transition and reduce errors and exceptions during the upgrade.
Here are a few tips:
- All obsolescence warnings begin with WARNING OF DEPRECATION & these warnings are available in your logs.
- Rails also allow us to throw an exception on the deprecation warning by setting config.active_support.deprecation=: increase in your development. rb file. This is the best approach to force developers to remove obsolete code.
- Shopify recently released a gem called deprecation-toolkit that helps you create a list called a shitlist of all deprecated warnings that you can store in a file and then delete them one by one.
- You should use rubocop in your codebase and run it regularly to maintain your codebase and remove outdated code.
It often happens that rail generators create files and code that we don’t intend to use or maybe we wrote some code and stopped using it. You should always delete this code whenever you find it to ensure that it does not cause problems in the future.
I personally recommend upgrading to the latest minor version of the current version before upgrading to the new version.
i.e. if you are currently using Rails 6.1.2 and you want to switch to sevenyou need to upgrade it to 6.1.6 first.
You should always follow the official release notes for the upgrade. For example, here are beautifully written release notes for moving to Rails 3: