From bbfc83af34e66702ca31ac8f3c260f5bbb39edee Mon Sep 17 00:00:00 2001 From: Eric Proulx Date: Sun, 14 Jun 2026 13:05:05 +0200 Subject: [PATCH] Detect the MultiXML constant to avoid the multi_xml deprecation multi_xml 0.9.0 deprecated the `MultiXml` constant in favor of `MultiXML` (removed in v1.0); the legacy constant warns on access/use. Grape detected the backend via `::MultiXml` and called `Grape::Xml.parse`, so users on multi_xml >= 0.9 would hit the deprecation. Detect `::MultiXML` first, falling back to the legacy `::MultiXml` constant and then `ActiveSupport::XmlMini`. Unlike multi_json, no facade is needed: `parse` is canonical (not renamed) and Grape only calls `parse`, so a direct alias suffices on every backend. Cover both multi_xml lines in CI: pin gemfiles/multi_xml.gemfile to >= 0.9 and add gemfiles/multi_xml_0_8.gemfile (< 0.9), each running the spec/integration/multi_xml suite. The integration spec now drives a real Grape API that parses an XML request body through Grape::Xml.parse. Co-Authored-By: Claude Opus 4.8 (1M context) --- .github/workflows/test.yml | 3 +++ CHANGELOG.md | 1 + gemfiles/multi_xml.gemfile | 2 +- gemfiles/multi_xml_0_8.gemfile | 5 +++++ lib/grape/xml.rb | 9 ++++++++- spec/integration/multi_xml/xml_spec.rb | 20 ++++++++++++++++++-- 6 files changed, 36 insertions(+), 4 deletions(-) create mode 100644 gemfiles/multi_xml_0_8.gemfile diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 1ff7c9974..cf7a70140 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -53,6 +53,9 @@ jobs: - ruby: '4.0' gemfile: gemfiles/multi_xml.gemfile specs: 'spec/integration/multi_xml' + - ruby: '4.0' + gemfile: gemfiles/multi_xml_0_8.gemfile + specs: 'spec/integration/multi_xml' runs-on: ubuntu-latest env: BUNDLE_GEMFILE: ${{ github.workspace }}/${{ matrix.gemfile }} diff --git a/CHANGELOG.md b/CHANGELOG.md index 0fe57e7c2..8f10c59ca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -75,6 +75,7 @@ * [#2706](https://github.com/ruby-grape/grape/pull/2706): Fix `optional :foo, message: 'oops'` raising `UnknownValidator` - [@ericproulx](https://github.com/ericproulx). * [#2751](https://github.com/ruby-grape/grape/pull/2751): Fix structured error messages leaking the raw i18n key for an undefined optional step such as `summary` (closes #2748) - [@ericproulx](https://github.com/ericproulx). * [#2759](https://github.com/ruby-grape/grape/pull/2759): Use `create_additions: false` in `Grape::Json.load` to prevent object instantiation via the `json_class` key when using the stdlib JSON fallback - [@dblock](https://github.com/dblock). +* [#2765](https://github.com/ruby-grape/grape/pull/2765): Detect the `MultiXML` constant to avoid the multi_xml 0.9 `MultiXml` deprecation - [@ericproulx](https://github.com/ericproulx). * Your contribution here. ### 3.2.1 (2026-04-16) diff --git a/gemfiles/multi_xml.gemfile b/gemfiles/multi_xml.gemfile index 3cd7774f9..8e1a50374 100644 --- a/gemfiles/multi_xml.gemfile +++ b/gemfiles/multi_xml.gemfile @@ -1,5 +1,5 @@ # frozen_string_literal: true -gem 'multi_xml' +gem 'multi_xml', '>= 0.9' eval_gemfile '../Gemfile' diff --git a/gemfiles/multi_xml_0_8.gemfile b/gemfiles/multi_xml_0_8.gemfile new file mode 100644 index 000000000..598a74e78 --- /dev/null +++ b/gemfiles/multi_xml_0_8.gemfile @@ -0,0 +1,5 @@ +# frozen_string_literal: true + +gem 'multi_xml', '< 0.9' + +eval_gemfile '../Gemfile' diff --git a/lib/grape/xml.rb b/lib/grape/xml.rb index 85287814a..9b6872808 100644 --- a/lib/grape/xml.rb +++ b/lib/grape/xml.rb @@ -1,7 +1,14 @@ # frozen_string_literal: true module Grape - if defined?(::MultiXml) + # Since multi_xml 0.9.0 the canonical constant is MultiXML; MultiXml is a + # deprecated alias (removed in v1.0) that warns on use. Prefer MultiXML so + # Grape::Xml.parse doesn't trip the deprecation, falling back to the legacy + # constant and then ActiveSupport::XmlMini. + # https://github.com/sferik/multi_xml/blob/v0.9.1/CHANGELOG.md + if defined?(::MultiXML) + Xml = ::MultiXML + elsif defined?(::MultiXml) Xml = ::MultiXml else Xml = ::ActiveSupport::XmlMini diff --git a/spec/integration/multi_xml/xml_spec.rb b/spec/integration/multi_xml/xml_spec.rb index a5d998847..740916e76 100644 --- a/spec/integration/multi_xml/xml_spec.rb +++ b/spec/integration/multi_xml/xml_spec.rb @@ -1,7 +1,23 @@ # frozen_string_literal: true describe Grape::Xml, if: defined?(MultiXml) do - subject { described_class } + # Exercise the full request stack: a Grape API parses an XML body through the + # active multi_xml backend (MultiXML on >= 0.9, the legacy MultiXml alias on + # < 0.9). Calling parse through the deprecated MultiXml constant would raise + # via the suite's deprecation handler (see spec/support/deprecated_warning_handlers.rb). + let(:app) do + Class.new(Grape::API) do + post '/request_body' do + params[:user] + end + end + end - it { is_expected.to eq(MultiXml) } + it 'parses an XML request body into params' do + env = Rack::MockRequest.env_for('/request_body', method: Rack::POST, input: 'Bobby T.', 'CONTENT_TYPE' => 'application/xml') + response = Rack::MockResponse[*app.call(env)] + + expect(response.status).to eq(201) + expect(response.body).to eq('Bobby T.') + end end