mirror of
https://github.com/stripe/stripe-ruby.git
synced 2025-10-03 00:01:21 -04:00
As described in #481, adding a protected field like `legal_entity` as part of an update API operation can cause some issues like a custom encoding scheme not being considered and special handling around empty values being ignored. As a an easy fix for this, let's disallow access to protected fields in the same way that we disallow them from being set directly on an instance of a given model. Helps address (but is not a complete fix for) #481.
88 lines
3.3 KiB
Ruby
88 lines
3.3 KiB
Ruby
module Stripe
|
|
module APIOperations
|
|
module Save
|
|
module ClassMethods
|
|
# Updates an API resource
|
|
#
|
|
# Updates the identified resource with the passed in parameters.
|
|
#
|
|
# ==== Attributes
|
|
#
|
|
# * +id+ - ID of the resource to update.
|
|
# * +params+ - A hash of parameters to pass to the API
|
|
# * +opts+ - A Hash of additional options (separate from the params /
|
|
# object values) to be added to the request. E.g. to allow for an
|
|
# idempotency_key to be passed in the request headers, or for the
|
|
# api_key to be overwritten. See {APIOperations::Request.request}.
|
|
def update(id, params={}, opts={})
|
|
params.each do |k, v|
|
|
if self.protected_fields.include?(k)
|
|
raise ArgumentError, "Cannot update protected field: #{k}"
|
|
end
|
|
end
|
|
|
|
response, opts = request(:post, "#{resource_url}/#{id}", params, opts)
|
|
Util.convert_to_stripe_object(response, opts)
|
|
end
|
|
end
|
|
|
|
# Creates or updates an API resource.
|
|
#
|
|
# If the resource doesn't yet have an assigned ID and the resource is one
|
|
# that can be created, then the method attempts to create the resource.
|
|
# The resource is updated otherwise.
|
|
#
|
|
# ==== Attributes
|
|
#
|
|
# * +params+ - Overrides any parameters in the resource's serialized data
|
|
# and includes them in the create or update. If +:req_url:+ is included
|
|
# in the list, it overrides the update URL used for the create or
|
|
# update.
|
|
# * +opts+ - A Hash of additional options (separate from the params /
|
|
# object values) to be added to the request. E.g. to allow for an
|
|
# idempotency_key to be passed in the request headers, or for the
|
|
# api_key to be overwritten. See {APIOperations::Request.request}.
|
|
def save(params={}, opts={})
|
|
# We started unintentionally (sort of) allowing attributes sent to
|
|
# +save+ to override values used during the update. So as not to break
|
|
# the API, this makes that official here.
|
|
update_attributes(params)
|
|
|
|
# Now remove any parameters that look like object attributes.
|
|
params = params.reject { |k, _| respond_to?(k) }
|
|
|
|
values = self.serialize_params(self).merge(params)
|
|
|
|
# note that id gets removed here our call to #url above has already
|
|
# generated a uri for this object with an identifier baked in
|
|
values.delete(:id)
|
|
|
|
response, opts = request(:post, save_url, values, opts)
|
|
initialize_from(response, opts)
|
|
|
|
self
|
|
end
|
|
|
|
def self.included(base)
|
|
base.extend(ClassMethods)
|
|
end
|
|
|
|
private
|
|
|
|
def save_url
|
|
# This switch essentially allows us "upsert"-like functionality. If the
|
|
# API resource doesn't have an ID set (suggesting that it's new) and
|
|
# its class responds to .create (which comes from
|
|
# Stripe::APIOperations::Create), then use the URL to create a new
|
|
# resource. Otherwise, generate a URL based on the object's identifier
|
|
# for a normal update.
|
|
if self[:id] == nil && self.class.respond_to?(:create)
|
|
self.class.resource_url
|
|
else
|
|
resource_url
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|