diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 128628a57..f0b184338 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -56,6 +56,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 dc43a3883..94f80a54e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -76,6 +76,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). * [#2764](https://github.com/ruby-grape/grape/pull/2764): Route `Grape::Json` through the non-deprecated `MultiJSON` API - [@ericproulx](https://github.com/ericproulx). * Your contribution here. 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