mirror of
https://github.com/stripe/stripe-ruby.git
synced 2025-10-09 00:03:05 -04:00
Merge pull request #454 from stripe/brandur-error-on-improper-array-of-maps
Produce an error on bad array of maps
This commit is contained in:
commit
ee03100891
@ -140,6 +140,7 @@ module Stripe
|
|||||||
if value.is_a?(Hash)
|
if value.is_a?(Hash)
|
||||||
result += flatten_params(value, calculated_key)
|
result += flatten_params(value, calculated_key)
|
||||||
elsif value.is_a?(Array)
|
elsif value.is_a?(Array)
|
||||||
|
check_array_of_maps_start_keys!(value)
|
||||||
result += flatten_params_array(value, calculated_key)
|
result += flatten_params_array(value, calculated_key)
|
||||||
else
|
else
|
||||||
result << [calculated_key, value]
|
result << [calculated_key, value]
|
||||||
@ -196,5 +197,44 @@ module Stripe
|
|||||||
raise TypeError.new("api_key must be a string") unless key.is_a?(String)
|
raise TypeError.new("api_key must be a string") unless key.is_a?(String)
|
||||||
key
|
key
|
||||||
end
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
# We use a pretty janky version of form encoding (Rack's) that supports
|
||||||
|
# more complex data structures like maps and arrays through the use of
|
||||||
|
# specialized syntax. To encode an array of maps like:
|
||||||
|
#
|
||||||
|
# [{a: 1, b: 2}, {a: 3, b: 4}]
|
||||||
|
#
|
||||||
|
# We have to produce something that looks like this:
|
||||||
|
#
|
||||||
|
# arr[][a]=1&arr[][b]=2&arr[][a]=3&arr[][b]=4
|
||||||
|
#
|
||||||
|
# The only way for the server to recognize that this is a two item array is
|
||||||
|
# that it notices the repetition of element "a", so it's key that these
|
||||||
|
# repeated elements are encoded first.
|
||||||
|
#
|
||||||
|
# This method is invoked for any arrays being encoded and checks that if
|
||||||
|
# the array contains all non-empty maps, that each of those maps must start
|
||||||
|
# with the same key so that their boundaries can be properly encoded.
|
||||||
|
def self.check_array_of_maps_start_keys!(arr)
|
||||||
|
expected_key = nil
|
||||||
|
arr.each do |item|
|
||||||
|
return if !item.is_a?(Hash)
|
||||||
|
return if item.count == 0
|
||||||
|
|
||||||
|
first_key = item.first[0]
|
||||||
|
|
||||||
|
if expected_key
|
||||||
|
if expected_key != first_key
|
||||||
|
raise ArgumentError,
|
||||||
|
"All maps nested in an array should start with the same key " +
|
||||||
|
"(expected starting key '#{expected_key}', got '#{first_key}')"
|
||||||
|
end
|
||||||
|
else
|
||||||
|
expected_key = first_key
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -138,7 +138,7 @@ module Stripe
|
|||||||
:amount => 100,
|
:amount => 100,
|
||||||
:source => 'btcrcv_test_receiver',
|
:source => 'btcrcv_test_receiver',
|
||||||
:currency => "usd",
|
:currency => "usd",
|
||||||
:level3 => [{:red => 'firstred'}, {:one => 'fish', :red => 'another'}]
|
:level3 => [{:red => 'firstred'}, {:red => 'another', :one => 'fish'}]
|
||||||
})
|
})
|
||||||
assert c.paid
|
assert c.paid
|
||||||
end
|
end
|
||||||
|
@ -20,6 +20,34 @@ module Stripe
|
|||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
should "#encode_params should throw an error on an array of maps that cannot be encoded" do
|
||||||
|
params = {
|
||||||
|
:a => [
|
||||||
|
{ :a => 1, :b => 2 },
|
||||||
|
{ :c => 3, :a => 4 },
|
||||||
|
]
|
||||||
|
}
|
||||||
|
e = assert_raises(ArgumentError) do
|
||||||
|
Stripe::Util.encode_parameters(params)
|
||||||
|
end
|
||||||
|
expected = "All maps nested in an array should start with the same key " +
|
||||||
|
"(expected starting key 'a', got 'c')"
|
||||||
|
assert_equal expected, e.message
|
||||||
|
|
||||||
|
# Make sure the check is recursive by taking our original params and
|
||||||
|
# nesting it into yet another map and array. Should throw exactly the
|
||||||
|
# same error because it's still the in inner array of maps that's wrong.
|
||||||
|
params = {
|
||||||
|
:x => [
|
||||||
|
params
|
||||||
|
]
|
||||||
|
}
|
||||||
|
e = assert_raises(ArgumentError) do
|
||||||
|
Stripe::Util.encode_parameters(params)
|
||||||
|
end
|
||||||
|
assert_equal expected, e.message
|
||||||
|
end
|
||||||
|
|
||||||
should "#url_encode should prepare strings for HTTP" do
|
should "#url_encode should prepare strings for HTTP" do
|
||||||
assert_equal "foo", Stripe::Util.url_encode("foo")
|
assert_equal "foo", Stripe::Util.url_encode("foo")
|
||||||
assert_equal "foo", Stripe::Util.url_encode(:foo)
|
assert_equal "foo", Stripe::Util.url_encode(:foo)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user