stripe 3.11.0 → 3.12.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA256:
3
- metadata.gz: 981d54e75ed0dc6a6c6e9134cbf338a2d8ed02e7169afc93f37c5c65d1e23955
4
- data.tar.gz: 844de1199f90a2e1eb32f2a011fda913b0ee3c799cd670c8dd42d441d0135805
2
+ SHA1:
3
+ metadata.gz: 78c2ddb890e46edf9e8e3d9b726ea6799d3aea52
4
+ data.tar.gz: ac32ac6e198a21dc2dd448a00601801d604e56fb
5
5
  SHA512:
6
- metadata.gz: 7890d0984cb8d83aec246a5fe745f2e57343e1b1c256343e79c49f35479de9cbafd90046dd00b537339a6b08257eb9dd39a1aa96f420059d5596584f7f2b7bd5
7
- data.tar.gz: 371d48d97dedf110422c91e70b25be7aa092576f55e87d5b1cf3e3d336b847ff9e0000fa18bd5f234459f33dd9b5826a7400fc53c7ac8939ac42de3c831220f3
6
+ metadata.gz: df6c4329f75ef7bb548630cc4d097d900b2a006c45d14c9bdea8884c9d27ccf7cfe746c302bc8e14bff25dc02c5a1d6b9f10967c97f86aa29628d6cfe0bcc5dd
7
+ data.tar.gz: 1e467d30f83de17b389f656343e90f5f9725e769e16b2c54fa755e8767cb7c13bb81d375f2671dccf8831d2d0a73f3a505939c3861860d9ecadf153a006d9d7d
@@ -22,7 +22,7 @@ Metrics/ClassLength:
22
22
 
23
23
  # Offense count: 11
24
24
  Metrics/CyclomaticComplexity:
25
- Max: 13
25
+ Max: 15
26
26
 
27
27
  # Offense count: 259
28
28
  # Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns.
@@ -47,7 +47,7 @@ Metrics/ParameterLists:
47
47
 
48
48
  # Offense count: 5
49
49
  Metrics/PerceivedComplexity:
50
- Max: 15
50
+ Max: 17
51
51
 
52
52
  # Offense count: 2
53
53
  Style/ClassVars:
@@ -1,5 +1,8 @@
1
1
  # Changelog
2
2
 
3
+ ## 3.12.0 - 2018-04-05
4
+ * [#632](https://github.com/stripe/stripe-ruby/pull/632) Introduce `additive_object_param` so that non-`metadata` subobjects don't zero their keys as they're being replaced
5
+
3
6
  ## 3.11.0 - 2018-02-26
4
7
  * [#628](https://github.com/stripe/stripe-ruby/pull/628) Add support for `code` attribute on all Stripe exceptions
5
8
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 3.11.0
1
+ 3.12.0
@@ -62,6 +62,15 @@ module Stripe
62
62
  end
63
63
 
64
64
  def self.included(base)
65
+ # Set `metadata` as additive so that when it's set directly we remember
66
+ # to clear keys that may have been previously set by sending empty
67
+ # values for them.
68
+ #
69
+ # It's possible that not every object with `Save` has `metadata`, but
70
+ # it's a close enough heuristic, and having this option set when there
71
+ # is no `metadata` field is not harmful.
72
+ base.additive_object_param(:metadata)
73
+
65
74
  base.extend(ClassMethods)
66
75
  end
67
76
 
@@ -7,6 +7,66 @@ module Stripe
7
7
  # The default :id method is deprecated and isn't useful to us
8
8
  undef :id if method_defined?(:id)
9
9
 
10
+ # Sets the given parameter name to one which is known to be an additive
11
+ # object.
12
+ #
13
+ # Additive objects are subobjects in the API that don't have the same
14
+ # semantics as most subobjects, which are fully replaced when they're set.
15
+ # This is best illustrated by example. The `source` parameter sent when
16
+ # updating a subscription is *not* additive; if we set it:
17
+ #
18
+ # source[object]=card&source[number]=123
19
+ #
20
+ # We expect the old `source` object to have been overwritten completely. If
21
+ # the previous source had an `address_state` key associated with it and we
22
+ # didn't send one this time, that value of `address_state` is gone.
23
+ #
24
+ # By contrast, additive objects are those that will have new data added to
25
+ # them while keeping any existing data in place. The only known case of its
26
+ # use is for `metadata`, but it could in theory be more general. As an
27
+ # example, say we have a `metadata` object that looks like this on the
28
+ # server side:
29
+ #
30
+ # metadata = { old: "old_value" }
31
+ #
32
+ # If we update the object with `metadata[new]=new_value`, the server side
33
+ # object now has *both* fields:
34
+ #
35
+ # metadata = { old: "old_value", new: "new_value" }
36
+ #
37
+ # This is okay in itself because usually users will want to treat it as
38
+ # additive:
39
+ #
40
+ # obj.metadata[:new] = "new_value"
41
+ # obj.save
42
+ #
43
+ # However, in other cases, they may want to replace the entire existing
44
+ # contents:
45
+ #
46
+ # obj.metadata = { new: "new_value" }
47
+ # obj.save
48
+ #
49
+ # This is where things get a little bit tricky because in order to clear
50
+ # any old keys that may have existed, we actually have to send an explicit
51
+ # empty string to the server. So the operation above would have to send
52
+ # this form to get the intended behavior:
53
+ #
54
+ # metadata[old]=&metadata[new]=new_value
55
+ #
56
+ # This method allows us to track which parameters are considered additive,
57
+ # and lets us behave correctly where appropriate when serializing
58
+ # parameters to be sent.
59
+ def self.additive_object_param(name)
60
+ @additive_params ||= Set.new
61
+ @additive_params << name
62
+ end
63
+
64
+ # Returns whether the given name is an additive object parameter. See
65
+ # `.additive_object_param` for details.
66
+ def self.additive_object_param?(name)
67
+ !@additive_params.nil? && @additive_params.include?(name)
68
+ end
69
+
10
70
  def initialize(id = nil, opts = {})
11
71
  id, @retrieve_params = Util.normalize_id(id)
12
72
  @opts = Util.normalize_opts(opts)
@@ -410,10 +470,14 @@ module Stripe
410
470
  elsif value.is_a?(StripeObject)
411
471
  update = value.serialize_params(force: force)
412
472
 
413
- # If the entire object was replaced, then we need blank each field of
414
- # the old object that held a value. The new serialized values will
415
- # override any of these empty values.
416
- update = empty_values(original).merge(update) if original && unsaved
473
+ # If the entire object was replaced and this is an additive object,
474
+ # then we need blank each field of the old object that held a value
475
+ # because otherwise the update to the keys of the object will be
476
+ # additive instead of a full replacement. The new serialized values
477
+ # will override any of these empty values.
478
+ if original && unsaved && key && self.class.additive_object_param?(key)
479
+ update = empty_values(original).merge(update)
480
+ end
417
481
 
418
482
  update
419
483
 
@@ -25,13 +25,8 @@ module Stripe
25
25
  end
26
26
 
27
27
  def serialize_params(options = {})
28
- update_hash = super
29
- if @unsaved_values.include?(:items)
30
- value = Util.array_to_hash(@values[:items])
31
- update_hash[:items] =
32
- serialize_params_value(value, nil, true, options[:force], key: :items)
33
- end
34
- update_hash
28
+ @values[:items] = Util.array_to_hash(@values[:items]) if @values[:items]
29
+ super
35
30
  end
36
31
 
37
32
  private
@@ -1,3 +1,3 @@
1
1
  module Stripe
2
- VERSION = "3.11.0".freeze
2
+ VERSION = "3.12.0".freeze
3
3
  end
@@ -303,12 +303,27 @@ module Stripe
303
303
  assert_equal({ foo: "bar" }, serialized[:metadata])
304
304
  end
305
305
 
306
- should "#serialize_params with a StripeObject that's been replaced" do
307
- obj = Stripe::StripeObject.construct_from(metadata: Stripe::StripeObject.construct_from(bar: "foo"))
306
+ should "#serialize_params with StripeObject that's been replaced" do
307
+ obj = Stripe::StripeObject.construct_from(source: Stripe::StripeObject.construct_from(bar: "foo"))
308
308
 
309
- # Here we replace the object wholesale which means that the client must
310
- # be able to blank out the values that were in the old object, but which
311
- # are no longer present in the new one.
309
+ # Here we replace the object wholesale.
310
+ obj.source =
311
+ Stripe::StripeObject.construct_from(baz: "foo")
312
+
313
+ serialized = obj.serialize_params
314
+ assert_equal({ baz: "foo" }, serialized[:source])
315
+ end
316
+
317
+ should "#serialize_params with StripeObject that's been replaced which is `metadata`" do
318
+ class WithAdditiveObjectParam < Stripe::StripeObject
319
+ additive_object_param :metadata
320
+ end
321
+
322
+ obj = WithAdditiveObjectParam.construct_from(metadata: Stripe::StripeObject.construct_from(bar: "foo"))
323
+
324
+ # Here we replace the object wholesale. Because it's `metadata`, the
325
+ # client must be able to blank out the values that were in the old
326
+ # object, but which are no longer present in the new one.
312
327
  obj.metadata =
313
328
  Stripe::StripeObject.construct_from(baz: "foo")
314
329
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: stripe
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.11.0
4
+ version: 3.12.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Stripe
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-02-26 00:00:00.000000000 Z
11
+ date: 2018-04-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday
@@ -184,7 +184,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
184
184
  version: '0'
185
185
  requirements: []
186
186
  rubyforge_project:
187
- rubygems_version: 2.7.6
187
+ rubygems_version: 2.6.14
188
188
  signing_key:
189
189
  specification_version: 4
190
190
  summary: Ruby bindings for the Stripe API