Skip to content

Commit

Permalink
Add last_response to StripeObject (#1377)
Browse files Browse the repository at this point in the history
* Add last_response to StripeObject

* Add more data to test and fix README
  • Loading branch information
helenye-stripe authored Apr 9, 2024
1 parent 5eb028c commit a12ff9c
Show file tree
Hide file tree
Showing 9 changed files with 45 additions and 20 deletions.
12 changes: 5 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -150,15 +150,13 @@ puts customer.unknown # raises NoMethodError

### Accessing a response object

Get access to response objects by initializing a client and using its `request`
method:
Get access to response objects by using the `last_response` property of the returned resource:

```ruby
client = Stripe::StripeClient.new
customer, resp = client.request do
Stripe::Customer.retrieve('cus_123456789',)
end
puts resp.request_id
customer = Stripe::Customer.retrieve('cus_123456789')

print(customer.last_response.http_status) # to retrieve status code
print(customer.last_response.http_headers) # to retrieve headers
```

### Configuring a proxy
Expand Down
4 changes: 2 additions & 2 deletions lib/stripe/api_operations/request.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ def execute_resource_request_stream(method, url,

private def request_stripe_object(method:, path:, params:, opts: {}, usage: [])
resp, opts = execute_resource_request(method, path, params, opts, usage)
Util.convert_to_stripe_object_with_params(resp.data, params, opts)
Util.convert_to_stripe_object_with_params(resp.data, params, opts, resp)
end

private def execute_resource_request_internal(client_request_method_sym,
Expand Down Expand Up @@ -129,7 +129,7 @@ def self.included(base)

private def request_stripe_object(method:, path:, params:, opts: {}, usage: [])
resp, opts = execute_resource_request(method, path, params, opts, usage)
Util.convert_to_stripe_object_with_params(resp.data, params, opts)
Util.convert_to_stripe_object_with_params(resp.data, params, opts, resp)
end

# See notes on `alias` above.
Expand Down
2 changes: 1 addition & 1 deletion lib/stripe/api_operations/save.rb
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ def save(params = {}, opts = {})
values.delete(:id)

resp, opts = execute_resource_request(:post, save_url, values, opts, ["save"])
initialize_from(resp.data, opts)
initialize_from(resp.data, opts, resp)
end
extend Gem::Deprecate
deprecate :save, "the `update` class method (for examples " \
Expand Down
2 changes: 1 addition & 1 deletion lib/stripe/api_operations/singleton_save.rb
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ def save(params = {}, opts = {})
values = serialize_params(self).merge(params)

resp, opts = execute_resource_request(:post, resource_url, values, opts, ["save"])
initialize_from(resp.data, opts)
initialize_from(resp.data, opts, resp)
end
extend Gem::Deprecate
deprecate :save, "the `update` class method (for examples " \
Expand Down
6 changes: 3 additions & 3 deletions lib/stripe/api_resource.rb
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ def resource_url
def refresh
resp, opts = execute_resource_request(:get, resource_url,
@retrieve_params)
initialize_from(resp.data, opts)
initialize_from(resp.data, opts, resp)
end

def self.retrieve(id, opts = {})
Expand All @@ -104,9 +104,9 @@ def request_stripe_object(method:, path:, params:, opts: {})

# If we're getting back this thing, update; otherwise, instantiate.
if Util.object_name_matches_class?(resp.data[:object], self.class)
initialize_from(resp.data, opts)
initialize_from(resp.data, opts, resp)
else
Util.convert_to_stripe_object_with_params(resp.data, params, opts)
Util.convert_to_stripe_object_with_params(resp.data, params, opts, resp)
end
end

Expand Down
11 changes: 8 additions & 3 deletions lib/stripe/stripe_object.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ module Stripe
class StripeObject
include Enumerable

attr_reader :last_response

@@permanent_attributes = Set.new([:id]) # rubocop:disable Style/ClassVars

# The default :id method is deprecated and isn't useful to us
Expand Down Expand Up @@ -80,13 +82,14 @@ def initialize(id = nil, opts = {})
@unsaved_values = Set.new
@transient_values = Set.new
@values[:id] = id if id
@last_response = nil
end

def self.construct_from(values, opts = {})
def self.construct_from(values, opts = {}, last_response = nil)
values = Stripe::Util.symbolize_names(values)

# work around protected #initialize_from for now
new(values[:id]).send(:initialize_from, values, opts)
new(values[:id]).send(:initialize_from, values, opts, last_response)
end

# Determines the equality of two Stripe objects. Stripe objects are
Expand Down Expand Up @@ -424,7 +427,9 @@ class << self; self; end
# * +:opts:+ Options for StripeObject like an API key.
# * +:partial:+ Indicates that the re-initialization should not attempt to
# remove accessors.
protected def initialize_from(values, opts)
protected def initialize_from(values, opts, last_response = nil)
@last_response = last_response

@opts = Util.normalize_opts(opts)

# the `#send` is here so that we can keep this method private
Expand Down
6 changes: 3 additions & 3 deletions lib/stripe/util.rb
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ def self.custom_method(resource, target, name, http_verb, http_path)
opts
)

Util.convert_to_stripe_object_with_params(resp.data, params, opts)
Util.convert_to_stripe_object_with_params(resp.data, params, opts, resp)
end
end

Expand Down Expand Up @@ -124,7 +124,7 @@ def self.convert_to_stripe_object(data, opts = {})
# * +data+ - Hash of fields and values to be converted into a StripeObject.
# * +opts+ - Options for +StripeObject+ like an API key that will be reused
# on subsequent API calls.
def self.convert_to_stripe_object_with_params(data, params, opts = {})
def self.convert_to_stripe_object_with_params(data, params, opts = {}, last_response = nil)
opts = normalize_opts(opts)

case data
Expand All @@ -135,7 +135,7 @@ def self.convert_to_stripe_object_with_params(data, params, opts = {})
# to generic StripeObject
object_name = data[:object] || data["object"]
obj = object_classes.fetch(object_name, StripeObject)
.construct_from(data, opts)
.construct_from(data, opts, last_response)

# set filters so that we can fetch the same limit, expansions, and
# predicates when accessing the next and previous pages
Expand Down
15 changes: 15 additions & 0 deletions test/stripe/stripe_client_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1584,5 +1584,20 @@ class SystemProfilerTest < Test::Unit::TestCase
_ = StripeClient::SystemProfiler.uname_from_system_ver
end
end

context "#last_response" do
should "return last_response with StripeObjects" do
stub_request(:get, "#{Stripe.api_base}/v1/charges")
.to_return(body: '{"id": "ch_123", "amount": "100"}')
charge = Stripe::Charge.list
assert_not_nil charge.last_response
assert charge.last_response.is_a?(Stripe::StripeResponse)
assert_equal 200, charge.last_response.http_status
assert_not_nil charge.last_response.http_headers
assert charge.last_response.http_headers.is_a?(Stripe::StripeResponseHeaders)
assert_not_nil charge.last_response.data
assert_equal({ id: "ch_123", amount: "100" }, charge.last_response.data)
end
end
end
end
7 changes: 7 additions & 0 deletions test/stripe/stripe_object_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -506,5 +506,12 @@ class WithAdditiveObjectParam < Stripe::StripeObject # rubocop:todo Lint/Constan
# Value still accessible with hash syntax
assert_equal "something", obj.metadata[:class]
end

context "#last_response" do
should "return raw response in last_response of object" do
obj = Stripe::StripeObject.construct_from({}, {}, { foo: "bar" })
assert_equal({ foo: "bar" }, obj.last_response)
end
end
end
end

0 comments on commit a12ff9c

Please sign in to comment.