Please read our consolidated guide to "modern Rubies" instead.
Note
You can find the updated guide here.
Rails 2.3 LTS works with Ruby 1.8.7, Ruby 2.5, and Ruby 2.7. Typical web apps see a 2x to 4x performance boost by switching from Ruby 1.8.7 to Ruby 2.5+. "Support" means that upgrading a Rails 2.3 application to Ruby 2.5 will not require Rails related monkey patches.
However, upgrading will still require some effort for the majority of Rails 2.3 applications, since your own code as well as some third-party gems will most likely have compatibility issues. You should only attempt this as a somewhat experienced Ruby developer, and only if you have a good automatic test suite, or if you're confident that you can manually test your application.
So far, we managed to upgrade two medium-sized applications of our own without major issues, in 1-2 days of effort each. It did require a few dozen minor changes, and we could only do this so quickly due to a very high test coverage. The upgraded apps run at roughly twice their former speed.
Upgrade workflow overview
-
If you haven't already, switch to bundler Show archive.org snapshot and migrate all
config.gem
lines to your Gemfile. -
Update to the latest version of Rails 2.3 LTS.
-
Switch your Ruby version to 2.5.x. (You can also first go to 2.3 and then 2.5 in a second step).
-
Add
test-unit
version1.2.3
withrequire: false
to your Gemfile (as a top-level gem and not inside thegroup :test
). -
Run
bundle install
. Make minimal version upgrades to your gems until all can be installed. See below -
In
config/preinitializer.rb
, add a lineEncoding.default_external = Encoding::UTF_8
-
In case you already were running on a Ruby > 1.8.7 and have made some Rails monkey patches yourself, remove them.
-
Check
script/server
,script/console
etc. The firstrequire
line should look like this:require File.expand_path('../../config/boot', __FILE__)
-
Run
script/console
and fix all errors. If you get a "cannot load such file" error, try runningscript/server
instead to get a full stacktrace. See below on how to fix common errors. -
Run
script/server
and fix all errors until a page renders. -
Run tests and fix remaining errors.
Rubygems
We recommend upgrading your RubyGems version to a modern 2.x version. This requires you to use bundler to manage your gems Show archive.org snapshot . Please see our RubyGems guide for additional details.
Third-party gems
Your application will probably depend on a bunch of other gems, and some of those might be incompatible with newer Rubies. The most common case are gems with native extensions that no longer compile.
You will have to check, whether these gems have an updated compatible version, can be removed, might be fixed with a monkey-patch, or have to be replaced.
An incomplete list of known incompatibilities:
-
date-performance
-> remove this, no longer necessary -
fastercsv
-> no longer required, Ruby now has builtinCSV
-
mysql
-> no longer compiles on Ruby 2.5, see below -
rspec
-> we have a working fork Show archive.org snapshot ofrspec 1.3.2
, see below -
sass
-> Current version (3.4.x) work
Mysql
The mysql
gem does no longer work on Ruby 2.5. Instead, use mysql2
, in a 0.2.x version (< 0.3
in your Gemfile should do).
mysql2
is mostly a drop in replacement for mysql
. The main API difference is that you might get casted values (i.e. Time
objects instead of strings) when you use some low-level methods of ActiveRecord, such as select_values
.
RSpec 1
If you application uses Rspec 1.x for testing, the easiest way forward is to upgrade rspec
and rspec-rails
to their latest RSpec 1 versions (1.3.2 for RSpec). You will also need to use our fork of rspec
, so change your Gemfile to
gem "rspec", "=1.3.2", git: 'https://github.com/makandra/rspec.git', branch: '1-3-lts'
You probably also want to use our fork or rspec-rails
which fixes a few test assertions:
gem "rspec-rails", "=1.3.5", git: 'https://github.com/makandra/rspec-rails.git', branch: '1-3-lts'
Common errors when upgrading
The following is a list of issues we encountered in our own code:
-
The YAML parser has changed from
Syck
toPsych
. Some.yaml
files need to be fixed for Psych. On common case can be found in default locale files. Instead oforder: [:day, :month, :year]
use
order: - :day - :month - :year
You also now need to quote strings starting with
*
or&
.Finally, if you made use of
ActiveRecord
'sserialize
feature, you might want to check that serialized data in your database can still be loaded. -
lambda
s (but notproc
s) have started to check their arguments. You can no longer call alambda
with additional arguments, if the block does not take any.
Fix this by simply switching the offending (or possible all)lambda
s toproc
s. -
Some methods in Ruby's standard library have changed:
-
object.respond_to?(:a_protected_method)
used to betrue
, but is nowfalse
. You can useobject.respond_to?(:a_protected_method, true)
(which will also be true for private methods, however). -
object.id
no longer aliasesobject.object_id
-
Array("line 1\nline 2")
no longer splits on linebreaks. Use"line 1\nline 2".lines
instead if you usedArray
for that purpose. -
Array+to_s
used to work likeArray#join
, but now works likeArray#inspec
. UseArray#join
explicitly. -
"some words".each
is gone. Use"some words".split.each
. - A few methods no longer accept symbols instead of strings (
"foo".starts_with?(:f)
is now an error):
-
-
You can potentially run into issues with String encoding. In general, everything should always be encoded as UTF-8. If you deal with binary data or lowlevel operations (like
String#unpack
), you must potentially useString#force_encoding
orString#encode
. -
Some default libraries are gone:
-
Instead of
FasterCSV
, useCSV
. It has the same Api, but can deal with encodings. -
iconv
is no longer in the standard library. You can add is a gem, or replace it withString#force_encoding
/String#encode
:# old converter = Iconv.new('UTF-8//IGNORE', 'WINDOWS-1252') converter.iconv(text) # new text.force_encoding('WINDOWS-1252').encode('UTF-8', undef: :replace, invalid: :replace)
-
-
Fixnum
deprecation warnings
In Ruby 2.4+Fixnum
andBignum
are deprecated and replaced by a unifiedInteger
class. This mostly just causes deprecation warnings but not actual errors, sinceFixnum
internally resolves toInteger
.If a third-party gem uses
Fixnum
and you want to remove the deprecation errors, you can often manually define aFixnum
class in the gems namespace. For example, we've added the following initializer to one of our projects:# config/initializer/fixnum_deprecation_fixes.rb # will_paginate WillPaginate::Fixnum = Integer BootstrapPagination::Fixnum = Integer # axlsx Axlsx::Fixnum = Integer