Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Reserve some critical field names when adding
StripeObject
accessors (
#970) When populating `StripeObject`s, we add accessors to them so that people can access fields like `obj.currency`. This was probably only meant to apply to API resources, but through what might have been an accident of history, we've also traditionally unmarshaled any hash that comes back from the API as a `StripeObject`, including `metadata` fields. This allows some convenience because users can access values like `obj.metadata.my_field`, but is also obviously a minefield for potential problems. In issue #969, what's essentially happening is that because there's a metadata field named `class`, we've overwritten the object's normal `class` method with our own custom one that accesses the metadata value. Amazingly, the object can still marshal/unmarshal mostly properly, but fails on this line as we try to access `obj.class` and that turns out to be a metadata value instead of a class: ``` ruby when StripeObject obj.class.construct_from( ... ``` Here I solve the problem by banning accessors added with the name `class`. This has a slight risk of backward incompatibility in that users that previously had metadata named "class" will now have to use square bracket accessors instead like `obj.metadata[:class]`, but honestly, I just can't see anything good in allowing "class" to be used as an accessor. An alternative solution might be to alias `class` in `StripeObject` and then make sure we always use that in places like `initialize_from` and `deep_copy`. The best long term solution would be to stop add accessors to metadata objects. This just seems like a bad idea given that there are still myriads of Ruby built-ins that could potentially be overwritten. This is definitely a considerably-sized breaking change though, so we'd have to do it on a major.
- Loading branch information