stripe-ruby/lib/stripe/account.rb
Brandur 863da48398 Add frozen_string_literal to every file and enforce Rubocop rule
Adds the magic `frozen_string_literal: true` comment to every file and
enables a Rubocop rule to make sure that it's always going to be there
going forward as well.

See here for more background [1], but the basic idea is that unlike many
other languages, static strings in code are mutable by default. This has
since been acknowledged as not a particularly good idea, and the
intention is to rectify the mistake when Ruby 3 comes out, where all
string literals will be frozen. The `frozen_string_literal` magic
comment was introduced in Ruby 2.3 as a way of easing the transition,
and allows libraries and projects to freeze their literals in advance.

I don't think this is breaking in any way: it's possible that users
might've been pulling out one of are literals somehow and mutating it,
but that would probably not have been useful for anything and would
certainly not be recommended, so I'm quite comfortable pushing this
change through as a minor version.

As discussed in #641.

[1] https://stackoverflow.com/a/37799399
2018-05-10 14:56:14 -07:00

141 lines
5.0 KiB
Ruby

# frozen_string_literal: true
module Stripe
class Account < APIResource
extend Gem::Deprecate
extend Stripe::APIOperations::Create
extend Stripe::APIOperations::List
include Stripe::APIOperations::Delete
include Stripe::APIOperations::Save
extend Stripe::APIOperations::NestedResource
OBJECT_NAME = "account".freeze
save_nested_resource :external_account
nested_resource_class_methods :external_account,
operations: %i[create retrieve update delete list]
nested_resource_class_methods :login_link, operations: %i[create]
# This method is deprecated. Please use `#external_account=` instead.
save_nested_resource :bank_account
deprecate :bank_account=, "#external_account=", 2017, 8
def resource_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
def reject(params = {}, opts = {})
opts = Util.normalize_opts(opts)
resp, opts = request(:post, resource_url + "/reject", params, opts)
initialize_from(resp.data, 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 serialize_params(options = {})
serialize_params_account(self, super)
end
def serialize_params_account(_obj, update_hash)
if (entity = @values[:legal_entity])
if (owners = entity[:additional_owners])
entity_update = update_hash[:legal_entity] ||= {}
entity_update[:additional_owners] =
serialize_additional_owners(entity, owners)
end
end
update_hash
end
def self.protected_fields
[:legal_entity]
end
def legal_entity
self["legal_entity"]
end
def legal_entity=(_)
raise NoMethodError, '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 = nil, opts = {})
params = {
client_id: client_id,
stripe_user_id: id,
}
OAuth.deauthorize(params, opts)
end
ARGUMENT_NOT_PROVIDED = Object.new
private
def serialize_additional_owners(legal_entity, additional_owners)
original_value = legal_entity.instance_variable_get(:@original_values)[:additional_owners]
if original_value && original_value.length > additional_owners.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, "You cannot delete an item from an array, you must instead set a new array"
end
update_hash = {}
additional_owners.each_with_index do |v, i|
# We will almost always see a StripeObject except in the case of a Hash
# that's been appended to an array of `additional_owners`. We may be
# able to normalize that ugliness by using an array proxy object with
# StripeObjects that can detect appends and replace a hash with a
# StripeObject.
update = v.is_a?(StripeObject) ? v.serialize_params : v
if update != {} && (!original_value ||
update != legal_entity.serialize_params_value(original_value[i], nil, false, true))
update_hash[i.to_s] = update
end
end
update_hash
end
end
end