Add RBI annotations for fields and params (#1559) (#1562)

* Introduce types to ruby

* rubocop

* forgot these files

* other request methods

* more tests, fix for raw request

* Add README entry for types

* rebase and regen
This commit is contained in:
helenye-stripe 2025-03-31 16:19:56 -07:00 committed by GitHub
commit a6c600a871
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 114 additions and 0 deletions

View File

@ -317,6 +317,35 @@ You can disable this behavior if you prefer:
Stripe.enable_telemetry = false
```
### Types
In [v14.0.0](https://github.com/stripe/stripe-python/releases/tag/v7.1.0) and newer, the library provides RBI
static type annotations. See [the wiki](https://github.com/stripe/stripe-ruby/wiki/Static-Type-Annotations)
for an detailed guide.
Please note that these types are available only for static analysis and we only support RBIs at the moment.
Please [report an issue](https://github.com/stripe/stripe-ruby/issues/new/choose)
if you find discrepancies or have issues using types.
The RBIs can be found in the `rbi/stripe/` directory, and to decrease `Tapioca` loading time we pack the gem with the
combined RBI at `rbi/stripe.rbi`.
#### Types and the Versioning Policy
We release type changes in minor releases. While stripe-ruby follows semantic versioning, our semantic
versions describe the runtime behavior of the library alone. Our type annotations are not reflected in the
semantic version. That is, upgrading to a new minor version of `stripe-ruby` might result in your type checker
producing a type error that it didn't before. You can use `~> x.x` or `x.x.x` constrain the version
of `stripe-ruby` in your Gemfile to a certain version or range of `stripe-ruby`.
#### Types and API Versions
The types describe the [Stripe API version](https://stripe.com/docs/api/versioning)
that was the latest at the time of release. This is the version that your library sends
by default. If you are overriding `Stripe.api_version` / `stripe_version` on the StripeClient,
or using a webhook endpoint tied to an older version, be aware that the data
you see at runtime may not match the types.
### Beta SDKs
Stripe has features in the beta phase that can be accessed via the beta version of this package.

View File

@ -222,6 +222,7 @@ module Stripe
params: {}, opts: {}, usage: [])
opts = RequestOptions.combine_opts(object.instance_variable_get(:@opts), opts)
opts = Util.normalize_opts(opts)
params = params.to_h if params.is_a?(RequestParams)
http_resp, req_opts = execute_request_internal(
method, path, base_address, params, opts, usage
)
@ -271,6 +272,7 @@ module Stripe
"execute_request_stream requires a read_body_chunk_block"
end
params = params.to_h if params.is_a?(RequestParams)
http_resp, api_key = execute_request_internal(
method, path, base_address, params, opts, usage, &read_body_chunk_block
)

View File

@ -74,6 +74,7 @@ module Stripe
opts = Util.normalize_opts(opts)
req_opts = RequestOptions.extract_opts_from_hash(opts)
params = params.to_h if params.is_a?(Stripe::RequestParams)
resp, = @requestor.send(:execute_request_internal, method, url, base_address, params, req_opts, usage: ["raw_request"])
@requestor.interpret_response(resp)

View File

@ -51,5 +51,87 @@ module Stripe
assert cus.is_a?(Stripe::Customer)
end
end
context "different request types" do
should "create a customer with params class" do
stub_request(:post, "#{Stripe.api_base}/v1/customers")
.with(body: "name=foo")
.to_return(body: JSON.generate(object: "customer", id: "cus_123", name: "foo"))
params = Stripe::Customer::CreateParams.new(name: "foo")
customer = Stripe::Customer.create(params)
assert customer.is_a?(Stripe::Customer)
assert_equal "cus_123", customer.id
assert_equal "foo", customer.name
end
should "update a customer with params class" do
stub_request(:post, "#{Stripe.api_base}/v1/customers/cus_123")
.with(body: "name=bar")
.to_return(body: JSON.generate(object: "customer", id: "cus_123", name: "bar"))
params = Stripe::Customer::UpdateParams.new(name: "bar")
customer = Stripe::Customer.update("cus_123", params)
assert customer.is_a?(Stripe::Customer)
assert_equal "cus_123", customer.id
assert_equal "bar", customer.name
end
# NOTE: Resource-based retrieve expand is a special case...
should "retrieve a customer with params class" do
stub_request(:get, "#{Stripe::DEFAULT_API_BASE}/v1/customers/cus_123?expand[]=foo")
.to_return(body: JSON.generate(object: "customer", id: "cus_123", name: "foo"))
@client = Stripe::StripeClient.new("sk_test_123")
customer = @client.v1.customers.retrieve("cus_123", CustomerService::RetrieveParams.new(expand: [:foo]))
assert customer.is_a?(Stripe::Customer)
end
should "list customers with params class" do
stub_request(:get, "#{Stripe.api_base}/v1/customers")
.to_return(body: JSON.generate(object: "list", data: [{ id: "cus_123", name: "foo" }, { id: "cus_456", name: "bar" }]))
customers = Stripe::Customer.list
assert customers.is_a?(Stripe::ListObject)
assert_equal 2, customers.data.size
assert_equal "cus_123", customers.data[0].id
assert_equal "foo", customers.data[0].name
assert_equal "cus_456", customers.data[1].id
assert_equal "bar", customers.data[1].name
end
should "search customers with params class" do
stub_request(:get, "#{Stripe.api_base}/v1/customers/search")
.with(query: { query: "name:'foo'" })
.to_return(body: JSON.generate(object: "search_result", data: [{ id: "cus_123", name: "foo" }]))
params = Stripe::Customer::SearchParams.new(query: "name:'foo'")
customers = Stripe::Customer.search(params)
assert customers.is_a?(Stripe::SearchResultObject)
assert_equal 1, customers.data.size
assert_equal "cus_123", customers.data[0].id
assert_equal "foo", customers.data[0].name
end
should "request params work in raw request" do
expected_body = JSON.generate(id: "cus_123", name: "foo")
req = nil
stub_request(:post, "#{Stripe::DEFAULT_API_BASE}/v1/customers")
.with(body: "name=foo")
.with { |request| req = request }
.to_return(body: expected_body)
@client = Stripe::StripeClient.new("sk_test_123")
resp = @client.raw_request(:post, "/v1/customers", params: Customer::CreateParams.new(name: "foo"))
assert_equal expected_body, resp.http_body
end
end
end
end