rexml used to be a a requirement of Rails as it is used as the default backend of ActiveSupport::XmlMini
. This backend is used e.g. when parsing XML payloads of API requests.
In Rails 6.1 the dependency to rexml
was removed but the default backend specification still remains.
In Ruby <= 2.7, the rexml library was included in the Ruby standard library. As such, it was still present and available even when not directly required. Starting with Ruby 3.0 however, rexml was converted into a bundled gem. As such, it is necessary to define it as a dependency in bundler (either explicitly or transitive via other dependencies). Now, if Redmine is installed with its test
group (which is the default), rexml is installed as transitive dependency to rubocop and is thus available.
However, if bundler is configured with
bundle config --without test
on Ruby >= 3.0, rexml
is not installed and is hidden by bundler, even if it's present as a bundled gem in Ruby. This results in ActiveSupport::XmlMini
trying to load rexml
fir its default backkend and failing.
We have two ways to resolve this:
- we could add a strict
rexml
dependency to the Gemfile
, effectively re-introducing the previous rails dependency:
gem "rexml", require: false
- Alternatively, we could switch to a different backend. As Redmine already depends on
nokogiri
, we could thus switch the XmlMini
backend to nokogiri in an initializer, e.g. config/initializers/30-redmine.rb
:
ActiveSupport::XmlMini.backend = 'Nokogiri'
This likely has the added benefit of (much) faster XML parsing and generation.