mirror of
https://github.com/stripe/stripe-ruby.git
synced 2025-10-15 00:00:44 -04:00
We attempt to do a special encoding trick when serializing `additional_owners` under an account: when updating a value, we actually send the update parameters up as an integer-indexed hash rather than an array. So instead of this: field[]=item1&field[]=item2&field[]=item3 We send this: field[0]=item1&field[1]=item2&field[2]=item3 The trouble is that this had previously been built into the core library as the default handling for all arrays. Because of this, it was impossible to resize a non-`additional_owners` array as described in more detail in #340. This patch special cases `additional_owners` and brings sane behavior back to normal arrays along with a test suite so that we try to build some better guarantees around both the general and non-general cases.
114 lines
4.0 KiB
Ruby
114 lines
4.0 KiB
Ruby
module Stripe
|
|
class Account < APIResource
|
|
extend Stripe::APIOperations::Create
|
|
include Stripe::APIOperations::Delete
|
|
extend Stripe::APIOperations::List
|
|
include Stripe::APIOperations::Update
|
|
|
|
def url
|
|
if self['id']
|
|
super
|
|
else
|
|
"/v1/account"
|
|
end
|
|
end
|
|
|
|
# @override To make id optional
|
|
def self.retrieve(id=ARGUMENT_NOT_PROVIDED, opts={})
|
|
id = id.equal?(ARGUMENT_NOT_PROVIDED) ? nil : Util.check_string_argument!(id)
|
|
|
|
# Account used to be a singleton, where this method's signature was
|
|
# `(opts={})`. For the sake of not breaking folks who pass in an OAuth
|
|
# key in opts, let's lurkily string match for it.
|
|
if opts == {} && id.is_a?(String) && id.start_with?('sk_')
|
|
# `super` properly assumes a String opts is the apiKey and normalizes as expected.
|
|
opts = id
|
|
id = nil
|
|
end
|
|
|
|
super(id, opts)
|
|
end
|
|
|
|
# Somewhat unfortunately, we attempt to do a special encoding trick when
|
|
# serializing `additional_owners` under an account: when updating a value,
|
|
# we actually send the update parameters up as an integer-indexed hash
|
|
# rather than an array. So instead of this:
|
|
#
|
|
# field[]=item1&field[]=item2&field[]=item3
|
|
#
|
|
# We send this:
|
|
#
|
|
# field[0]=item1&field[1]=item2&field[2]=item3
|
|
#
|
|
# There are two major problems with this technique:
|
|
#
|
|
# * Entities are addressed by array index, which is not stable and can
|
|
# easily result in unexpected results between two different requests.
|
|
#
|
|
# * A replacement of the array's contents is ambiguous with setting a
|
|
# subset of the array. Because of this, the only way to shorten an
|
|
# array is to unset it completely by making sure it goes into the
|
|
# server as an empty string, then setting its contents again.
|
|
#
|
|
# We're trying to get this overturned on the server side, but for now,
|
|
# patch in a special allowance.
|
|
def self.serialize_params(obj, original_value=nil)
|
|
update_hash = StripeObject.serialize_params(obj, original_value)
|
|
case obj
|
|
when StripeObject
|
|
obj_values = obj.instance_variable_get(:@values)
|
|
obj_values.each do |k, v|
|
|
if k == :additional_owners && v.is_a?(Array)
|
|
update_hash[k] = serialize_additional_owners(obj, v)
|
|
end
|
|
end
|
|
end
|
|
update_hash
|
|
end
|
|
|
|
def protected_fields
|
|
[:legal_entity]
|
|
end
|
|
|
|
def legal_entity
|
|
self['legal_entity']
|
|
end
|
|
|
|
def legal_entity=(_)
|
|
raise NoMethodError.new('Overridding legal_entity can cause serious issues. Instead, set the individual fields of legal_entity like blah.legal_entity.first_name = \'Blah\'')
|
|
end
|
|
|
|
def deauthorize(client_id, opts={})
|
|
opts = {:api_base => Stripe.connect_base}.merge(Util.normalize_opts(opts))
|
|
response, opts = request(:post, '/oauth/deauthorize', { 'client_id' => client_id, 'stripe_user_id' => self.id }, opts)
|
|
opts.delete(:api_base) # the api_base here is a one-off, don't persist it
|
|
Util.convert_to_stripe_object(response, opts)
|
|
end
|
|
|
|
ARGUMENT_NOT_PROVIDED = Object.new
|
|
|
|
private
|
|
|
|
def self.serialize_additional_owners(obj, value)
|
|
original_value = obj.instance_variable_get(:@original_values)[:additional_owners]
|
|
if original_value && original_value.length > value.length
|
|
# url params provide no mechanism for deleting an item in an array,
|
|
# just overwriting the whole array or adding new items. So let's not
|
|
# allow deleting without a full overwrite until we have a solution.
|
|
raise ArgumentError.new(
|
|
"You cannot delete an item from an array, you must instead set a new array"
|
|
)
|
|
end
|
|
|
|
update_hash = {}
|
|
value.each_with_index do |v, i|
|
|
update = StripeObject.serialize_params(v)
|
|
if update != {} && (!original_value || update != original_value[i])
|
|
update_hash[i.to_s] = update
|
|
end
|
|
end
|
|
update_hash
|
|
end
|
|
end
|
|
end
|