Upgrade Ruby from 3.0 to 3.2
升级 Ruby 到 3.2
Now that Ruby 3.3 preview 2 has been released, I've been working on upgrading a 3.0 project to 3.2. I've encountered a few problems with upgrading from 3.0 to 3.2, so I'm going to try to organize them here, and hopefully they'll help.
In Ruby 3.1, some libs went from being standard libraries to bundled gems, such as net-ftp, which I use in my projects, and libraries like matrix. The list can be seen at Ruby 3.1.0 Released, scroll down to the "Standard libraries updates" section.
This means that if we're using bundlers, we need to add gems like matrix to our Gemfile, otherwise we'll run into this problem:
Rails `require': cannot load such file -- matrix
By the way, there are some differences between bundled gems and default libraries.
In the case of matrix, for example, in Ruby 3.1,
matrix has been changed from being part of the Ruby standard library to being a bundled gem. This change does not mean that it has been removed from Ruby's default libraries, but rather that matrix is now considered a gem.
bundled gems: these libs are now treated as gems, and we need to include them in our Gemfile when creating a new Ruby project using the bundler, but as bundled gems we don't need to install them individually, they are
default libraries: these libraries are still provided in the standard library when installing Ruby, i.e. we can still access them when using pure Ruby.
Psych (YAML) Security Updates
There have been some breaking changes in the behavior of YAML's
load_file methods, mainly in the underlying Psych library.
YAML.load that used to work correctly may now throw this error:
YAML.load "--- !ruby/object:Matrix\nrows:\n- - 25\n - 93\n- - -1\n - 66\ncolumn_count: 2\n" Psych::DisallowedClass: Tried to load unspecified class: Matrix
This is because
YAML.load now calls
Psych.safe_load, which restricts the kinds of Ruby objects that are safe when parsing yaml.
The workaround is as follows:
if you trust your data then replace
If you don't trust the content of your data, then you need to add the permited_classes parameter, as follows:
YAML.load "--- !ruby/object:Matrix\nrows:\n- - 25\n - 93\n- - -1\n - 66\ncolumn_count: 2\n", permitted_classes: [Matrix] => Matrix[[25, 93], [-1, 66]]
In a Rails project, you can also configure
config/application.rb as follows:
config.after_initialize do ActiveRecord.yaml_column_permitted_classes += [Date, Time, ActiveSupport::HashWithIndifferentAccess] end
The context of this change can be seen here: [CVE-2022-32224] Possible RCE escalation bug with Serialized Columns in Active Record
Deprecating methods that are finally removed after a long time
File.exists? was marked as Deprecating since Ruby 2.1, but it didn't say when it would be removed. After upgrading to Ruby 3.2, I encountered the error
undefined method 'exists?' for File:Class, and realized that it had finally been removed. Also removed was the
Dir.exists? method. See the "Removed methods" section in the release notes.
However, after searching the project globally and replacing
File.exist?, I still get a similar error. This is because in the chef script (I copied and pasted from the Internet), there is also a usage of
I then checked that the test methods
File.file? are acutally defined in the
FileTest module, which was included by the File class, and Ruby allows us to call these methods directly from FileTest. Therefore, the use of
FileTest.exists? needs to be changed to