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
This commit is contained in:
Cillian O'Ruanaidh
2020-10-24 15:06:30 +01:00
parent 6b826423c1
commit ea3c456d3b
3 changed files with 66 additions and 0 deletions

View File

@@ -0,0 +1 @@
require "action_dispatch/request"

View File

@@ -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

View File

@@ -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