Overrides `#eql?` (hash equality) and `#hash` so that Stripe objects can
be used more easily as Hash keys and that certain other frameworks that
rely on these methods will have an easier time (e.g. RSpec's `change`,
see #687).
I think this might be a little controversial if we weren't already
overriding the `#==` implementation, but because we are, I think it
makes sense to extent it to these two methods as well.
I was testing with a new version of stripe-mock and it caught a few
problems with query parameter validation on. This patch contains some
minor fixes to address them.
Changes all arrays from classic Rack encoding:
``` sh
arr[]=...&arr[]=...&arr[]=...
```
To integer-indexed encoding:
``` sh
arr[0]=...&arr[1]=...&arr[2]=...
```
We think that this should be tractable now that we've fully converted
all endpoints over to the new AbstractAPIMethod infrastructure on the
backend (although we should do a little more testing to make sure that
all endpoints still work).
As part of the conversion, we also remove any places that we were "spot
encoding" to get required integer-indexed syntax. This should now all be
built in.
This changes the predicate supplied to the #colorize method to ensure
that if a logger is set, the colorizing ANSI escape codes are not applied.
This definitely appears to have been the intention behind the original
implementation, but the tests didn't reflect how .log_internal was
actually called. In reality, it is always supplied with an `out:`
argument, not nil. This caused all logger bound output to also be
colorized.
I found a bug recently in stripe-mock which causes it not to actually be
validating that parameters not in the spec are not being sent (the
actual Stripe API does check for this).
After applying a fix, I found that stripe-ruby's test suite no longer
passes against it, and the reason is that there are some subtle mistakes
throughout. This patch corrects them to be in line with what the API
actually expects.
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
If specifying both query parameters in a path/URL down to Faraday (e.g.,
`/v1/invoices/upcoming?coupon=25OFF`) _and_ query parameters in a hash
(e.g., `{ customer: "cus_123" }`), it will silently overwrite the ones
in the path with the ones in the hash. This can cause problems where
some critical parameters are discarded and causes an error, as seen in
issue #646.
This patch modifies `#execute_request` so that before going out to
Faraday we check whether the incoming path has query parameters. If it
does, we decode them and add them to our `query_params` hash so that
all parameters from either place are preserved.
Fixes#646.
`stripe-mock` can now respond accurately for file API endpoints thanks
to a few improvements in how it handles `multipart/form-data` payloads
and the OpenAPI spec.
Here we upgrade `stripe-mock` to 0.15.0 and remove the manual stubbing
that we had previously.
So we have a bit of a problem right now when it comes to replacing a
`StripeObject` that's embedded in an API resource.
Most of the time when someone does this, they want to _replace_ an
object embedded in another object. Take setting a source on a
subscription for example:
``` ruby
subscription.source = {
object: 'card',
number: 123,
}
subscription.save
```
In the case above, the serialized parameters should come out as:
```
source[object]=card&source[number]=123
```
That should apply even if the previous source had something else set on
it which we're not going to set this time -- say an optional parameter
like `source[address_state]`. Those should not be present at all in the
final serialized parameters.
(Another example is setting a `payout_schedule` as seen in #631 which is
PR is intended to address.)
There is an exception to this rule in the form of metadata though.
Metadata is a bit of a strange case in that the API will treat it as
additive, so if we send `metadata[foo]`, that will set the `foo` key,
but it won't overwrite any other keys that were already present.
This is a problem because when a user fully sets `metadata` to a new
object in Ruby, what they're probably trying to do is _replace_ it
rather than add to it. For example:
``` ruby
subscription.metadata
=> { old: 'bar' }
subscription.metadata = {
new: 'baz'
}
subscription.save
```
To accomplish what the user is probably trying to do, we actually need
to send `metadata[old]=&metadata[new]=baz` so that we empty the value of
`old` while simultaneously setting `new` to `baz`.
In summary, metadata behaves different from other embedded objects in a
fairly fundamental way, and because the code is currently only set up to
handle the metadata case, it's not behaving correctly when other types
of objects are being set. A lot of the time emptying values like we do
for `metadata` is benign, but as we've seen in #631, sometimes it's not.
In this patch, I modify serialization to only empty out object values
when we see that parameter is `metadata`.
I'm really not crazy about the implementation here _at all_, but I'm
having trouble thinking of a better way to do it. One possibility is to
introduce a new class annotation like `empty_embedded_object :metadata`,
but that will have to go everywhere and might be error-prone in case
someone forgets it on a new resource type. If anyone has a suggestion
for an alternative (or can let me know if I'm missing something), I'd
love to hear it.
This PR is an alternate to #631.
A few weeks back a new error type `idempotency_error` was introduced in
the API. I put it in to respond to #503, but then forgot to add support
for it in this library. This patch introduces a new exception class that
represents it.
stripe-mock 0.4.0 comes with the up-to-date exchange rates API. Here we
bump the required version and remove the manual exchange rate stubbing
in stripe-ruby's test suite.
Makes the `operations` argument to `nested_resource_class_methods`
required and adds explicit lists to any invocations that were missing
one.
The impetus here is that I think it's more easily digestible if each
call site is explicit about what operations it supports and therefore
which methods it's about to create on the class.