From ea3c456d3b34992240f6225c93a39bb285d9cf4a Mon Sep 17 00:00:00 2001 From: Cillian O'Ruanaidh Date: Sat, 24 Oct 2020 15:06:30 +0100 Subject: [PATCH] Patch Rails :deep_munge issue so empty array parameters don't get converted to nil Before people were unable to remove coordinator fees from an order cycle because Rails was converting the empty :coordinator_fee_ids array paramter into nil. This issue was introduced to Rails in v4.0.0.beta1 and isn't fixed until v5.0.0.beta1 Another way to fix this could be to do something like 'params[:coordinator_fee_ids] ||= []' but it seems like this issue could problems in other parts of the app so a more general fix might be better. Fixes #6224 --- ...ction_dispatch_request_deep_munge_patch.rb | 1 + lib/action_dispatch/request.rb | 47 +++++++++++++++++++ spec/lib/action_dispatch/request_spec.rb | 18 +++++++ 3 files changed, 66 insertions(+) create mode 100644 config/initializers/action_dispatch_request_deep_munge_patch.rb create mode 100644 lib/action_dispatch/request.rb create mode 100644 spec/lib/action_dispatch/request_spec.rb diff --git a/config/initializers/action_dispatch_request_deep_munge_patch.rb b/config/initializers/action_dispatch_request_deep_munge_patch.rb new file mode 100644 index 0000000000..9967e08a0b --- /dev/null +++ b/config/initializers/action_dispatch_request_deep_munge_patch.rb @@ -0,0 +1 @@ +require "action_dispatch/request" diff --git a/lib/action_dispatch/request.rb b/lib/action_dispatch/request.rb new file mode 100644 index 0000000000..681d0890bc --- /dev/null +++ b/lib/action_dispatch/request.rb @@ -0,0 +1,47 @@ +# This patch fixes the Rails issue where ActionDispatch::Request#deep_munge was converting empty +# array paramters into nils, see https://github.com/rails/rails/issues/13420 +# +# Before this patch: +# +# | JSON | Hash | +# |----------------------------------|-------------------------| +# | { "person": [] } | { 'person' => nil } | +# +# After patch: +# +# | JSON | Hash | +# |----------------------------------|-------------------------| +# | { "person": [] } | { 'person' => [] } | +# +# The issue started in Rails v4.0.0.beta1: +# +# https://github.com/rails/rails/commit/8e577fe560d5756fcc67840ba304d79ada6804e4 +# +# This patch can be removed on or after Rails v5.0.0.beta1 when the issue was fixed: +# +# https://github.com/rails/rails/commit/8f8ccb9901cab457c6e1d52bdb25acf658fd5777 +# +# Credit: +# +# https://gist.github.com/victorblasco/f675b4cbaf9c0bc19f81 + +module ActionDispatch + class Request + def deep_munge(hash) + hash.each do |k, v| + case v + when Array + v.grep(Hash) { |x| deep_munge(x) } + v.compact! + + # This patch removes the next line + # hash[k] = nil if v.empty? + when Hash + deep_munge(v) + end + end + + hash + end + end +end diff --git a/spec/lib/action_dispatch/request_spec.rb b/spec/lib/action_dispatch/request_spec.rb new file mode 100644 index 0000000000..c0ab839f08 --- /dev/null +++ b/spec/lib/action_dispatch/request_spec.rb @@ -0,0 +1,18 @@ +require 'spec_helper' + +describe ActionDispatch::Request do + it "strips nils from arrays" do + assert_parses({ "key" => ["value"] }, 'key[]=value&key[]') + assert_parses({ "key1" => { "key2" => ["value"] } }, 'key1[key2][]=value&key1[key2][]') + end + + it "doesn't convert an empty array to nil" do + assert_parses({ "key" => [] }, 'key[]') + end + + private + + def assert_parses(expected, actual) + assert_equal expected, ActionDispatch::Request.new('QUERY_STRING' => actual).query_parameters + end +end