Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions lib/stripe/api_requestor.rb
Original file line number Diff line number Diff line change
Expand Up @@ -471,17 +471,17 @@ def self.maybe_gc_connection_managers
raise ArgumentError, "api_base cannot be empty" if base_url.nil? || base_url.empty?

api_key ||= opts[:api_key]
params = Util.objects_to_ids(params, api_mode)

check_api_key!(api_key)

body_params = nil
query_params = nil
case method
when :get, :head, :delete
query_params = params
query_params = Util.objects_to_ids(params)
else
body_params = params
# For v2 body params, serialize nil values to preserve explicit nulls
body_params = Util.objects_to_ids(params, serialize_empty: api_mode == :v2)
end

query_params, path = merge_query_params(query_params, path)
Expand Down
8 changes: 4 additions & 4 deletions lib/stripe/util.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,22 @@ module Util
LEGAL_FIRST_CHARACTER = /[a-zA-Z_]/.freeze
LEGAL_VARIABLE_CHARACTER = /[a-zA-Z0-9_]/.freeze

def self.objects_to_ids(obj, semantics)
def self.objects_to_ids(obj, serialize_empty: false)
case obj
when APIResource
obj.id
when Hash
res = {}
obj.each do |k, v|
if !v.nil?
res[k] = objects_to_ids(v, semantics)
elsif semantics == :v2
res[k] = objects_to_ids(v, serialize_empty: serialize_empty)
elsif serialize_empty
res[k] = nil
end
end
res
when Array
obj.map { |v| objects_to_ids(v, semantics) }
obj.map { |v| objects_to_ids(v, serialize_empty: serialize_empty) }
else
obj
end
Expand Down
48 changes: 24 additions & 24 deletions test/stripe/util_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -161,53 +161,53 @@ class UtilTest < Test::Unit::TestCase
context "#objects_to_ids" do
should "convert APIResource to id" do
resource = Stripe::Charge.construct_from(id: "ch_123", object: "charge")
result = Util.objects_to_ids(resource, :v1)
result = Util.objects_to_ids(resource)
assert_equal "ch_123", result
end

should "pass through primitives unchanged" do
assert_equal "string", Util.objects_to_ids("string", :v1)
assert_equal 123, Util.objects_to_ids(123, :v1)
assert_equal true, Util.objects_to_ids(true, :v1)
assert_equal "string", Util.objects_to_ids("string")
assert_equal 123, Util.objects_to_ids(123)
assert_equal true, Util.objects_to_ids(true)
end

should "skip nil values in hashes with v1 semantics" do
should "skip nil values in hashes by default" do
input = { a: "value", b: nil, c: "another" }
result = Util.objects_to_ids(input, :v1)
result = Util.objects_to_ids(input)
assert_equal({ a: "value", c: "another" }, result)
refute result.key?(:b)
end

should "keep nil values in hashes with v2 semantics" do
should "keep nil values in hashes when serialize_empty is true" do
input = { a: "value", b: nil, c: "another" }
result = Util.objects_to_ids(input, :v2)
result = Util.objects_to_ids(input, serialize_empty: true)
assert_equal({ a: "value", b: nil, c: "another" }, result)
assert result.key?(:b)
assert_nil result[:b]
end

should "recurse on non-nil hash values with v1 semantics" do
should "recurse on non-nil hash values by default" do
resource = Stripe::Charge.construct_from(id: "ch_123", object: "charge")
input = { charge: resource, amount: 100 }
result = Util.objects_to_ids(input, :v1)
result = Util.objects_to_ids(input)
assert_equal({ charge: "ch_123", amount: 100 }, result)
end

should "recurse on non-nil hash values with v2 semantics" do
should "recurse on non-nil hash values when serialize_empty is true" do
resource = Stripe::Charge.construct_from(id: "ch_123", object: "charge")
input = { charge: resource, amount: 100 }
result = Util.objects_to_ids(input, :v2)
result = Util.objects_to_ids(input, serialize_empty: true)
assert_equal({ charge: "ch_123", amount: 100 }, result)
end

should "handle nested hashes with nil values in v1 semantics" do
should "handle nested hashes with nil values by default" do
resource = Stripe::Charge.construct_from(id: "ch_123", object: "charge")
input = {
charge: resource,
metadata: { key: "value", empty: nil },
description: nil,
}
result = Util.objects_to_ids(input, :v1)
result = Util.objects_to_ids(input)
expected = {
charge: "ch_123",
metadata: { key: "value" },
Expand All @@ -217,14 +217,14 @@ class UtilTest < Test::Unit::TestCase
refute result.key?(:description)
end

should "handle nested hashes with nil values in v2 semantics" do
should "handle nested hashes with nil values when serialize_empty is true" do
resource = Stripe::Charge.construct_from(id: "ch_123", object: "charge")
input = {
charge: resource,
metadata: { key: "value", empty: nil },
description: nil,
}
result = Util.objects_to_ids(input, :v2)
result = Util.objects_to_ids(input, serialize_empty: true)
expected = {
charge: "ch_123",
metadata: { key: "value", empty: nil },
Expand All @@ -235,43 +235,43 @@ class UtilTest < Test::Unit::TestCase
assert result.key?(:description)
end

should "process arrays with v1 semantics" do
should "process arrays by default" do
resource1 = Stripe::Charge.construct_from(id: "ch_123", object: "charge")
resource2 = Stripe::Charge.construct_from(id: "ch_456", object: "charge")
input = [resource1, "string", resource2]
result = Util.objects_to_ids(input, :v1)
result = Util.objects_to_ids(input)
assert_equal %w[ch_123 string ch_456], result
end

should "process arrays with v2 semantics" do
should "process arrays when serialize_empty is true" do
resource1 = Stripe::Charge.construct_from(id: "ch_123", object: "charge")
resource2 = Stripe::Charge.construct_from(id: "ch_456", object: "charge")
input = [resource1, "string", resource2]
result = Util.objects_to_ids(input, :v2)
result = Util.objects_to_ids(input, serialize_empty: true)
assert_equal %w[ch_123 string ch_456], result
end

should "handle complex nested structures with v1 semantics" do
should "handle complex nested structures by default" do
resource = Stripe::Charge.construct_from(id: "ch_123", object: "charge")
input = {
charges: [resource, nil],
metadata: { key: nil, nested: { value: "test", empty: nil } },
}
result = Util.objects_to_ids(input, :v1)
result = Util.objects_to_ids(input)
expected = {
charges: ["ch_123", nil],
metadata: { nested: { value: "test" } },
}
assert_equal expected, result
end

should "handle complex nested structures with v2 semantics" do
should "handle complex nested structures when serialize_empty is true" do
resource = Stripe::Charge.construct_from(id: "ch_123", object: "charge")
input = {
charges: [resource, nil],
metadata: { key: nil, nested: { value: "test", empty: nil } },
}
result = Util.objects_to_ids(input, :v2)
result = Util.objects_to_ids(input, serialize_empty: true)
expected = {
charges: ["ch_123", nil],
metadata: { key: nil, nested: { value: "test", empty: nil } },
Expand Down