chartmogul-ruby 1.4.1 → 1.6.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (76) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +8 -1
  3. data/Gemfile +2 -0
  4. data/LICENSE.txt +1 -1
  5. data/README.md +5 -3
  6. data/Rakefile +2 -0
  7. data/bin/console +1 -0
  8. data/changelog.md +3 -0
  9. data/chartmogul-ruby.gemspec +14 -11
  10. data/fixtures/vcr_cassettes/ChartMogul_APIResource/connection/works_in_a_threaded_environment.yml +112 -0
  11. data/fixtures/vcr_cassettes/ChartMogul_APIResource/connection/works_when_credentials_are_updated.yml +77 -0
  12. data/fixtures/vcr_cassettes/ChartMogul_Customer/API_Interactions/updates_customer_using_class_method.yml +53 -0
  13. data/fixtures/vcr_cassettes/ChartMogul_Plan/API_Interactions/updates_existing_plan_using_class_method.yml +164 -0
  14. data/fixtures/vcr_cassettes/ChartMogul_PlanGroup/API_interactions/correctly_handles_a_422_error.yml +50 -0
  15. data/fixtures/vcr_cassettes/ChartMogul_PlanGroup/API_interactions/deletes_a_plan_group.yml +293 -0
  16. data/fixtures/vcr_cassettes/ChartMogul_PlanGroup/API_interactions/retrieves_existing_plan_group_by_uuid.yml +251 -0
  17. data/fixtures/vcr_cassettes/ChartMogul_PlanGroup/API_interactions/returns_an_array_of_plan_groups.yml +357 -0
  18. data/fixtures/vcr_cassettes/ChartMogul_PlanGroup/API_interactions/updates_existing_plan_group_name.yml +304 -0
  19. data/fixtures/vcr_cassettes/ChartMogul_PlanGroup/API_interactions/updates_existing_plan_group_name_via_class_method.yml +297 -0
  20. data/fixtures/vcr_cassettes/ChartMogul_PlanGroup/API_interactions/updates_existing_plan_group_plans.yml +411 -0
  21. data/fixtures/vcr_cassettes/ChartMogul_PlanGroups_Plans/API_interactions/given_a_plan_group_uuid_returns_an_array_of_plans_in_the_plan_group.yml +252 -0
  22. data/lib/chartmogul.rb +9 -2
  23. data/lib/chartmogul/api/actions/all.rb +2 -0
  24. data/lib/chartmogul/api/actions/create.rb +2 -0
  25. data/lib/chartmogul/api/actions/custom.rb +2 -0
  26. data/lib/chartmogul/api/actions/destroy.rb +2 -0
  27. data/lib/chartmogul/api/actions/retrieve.rb +2 -0
  28. data/lib/chartmogul/api/actions/update.rb +22 -0
  29. data/lib/chartmogul/api_resource.rb +21 -12
  30. data/lib/chartmogul/concerns/entries.rb +2 -0
  31. data/lib/chartmogul/concerns/pageable.rb +2 -0
  32. data/lib/chartmogul/concerns/pageable2.rb +2 -0
  33. data/lib/chartmogul/concerns/summary.rb +2 -0
  34. data/lib/chartmogul/config_attributes.rb +7 -1
  35. data/lib/chartmogul/configuration.rb +2 -0
  36. data/lib/chartmogul/customer.rb +2 -0
  37. data/lib/chartmogul/customer_invoices.rb +2 -0
  38. data/lib/chartmogul/data_source.rb +2 -0
  39. data/lib/chartmogul/enrichment/customer.rb +2 -0
  40. data/lib/chartmogul/errors/chartmogul_error.rb +2 -0
  41. data/lib/chartmogul/errors/configuration_error.rb +2 -0
  42. data/lib/chartmogul/errors/forbidden_error.rb +2 -0
  43. data/lib/chartmogul/errors/not_found_error.rb +2 -0
  44. data/lib/chartmogul/errors/resource_invalid_error.rb +2 -0
  45. data/lib/chartmogul/errors/schema_invalid_error.rb +2 -0
  46. data/lib/chartmogul/errors/server_error.rb +2 -0
  47. data/lib/chartmogul/errors/unauthorized_error.rb +2 -0
  48. data/lib/chartmogul/invoice.rb +2 -0
  49. data/lib/chartmogul/line_items/one_time.rb +2 -0
  50. data/lib/chartmogul/line_items/subscription.rb +2 -0
  51. data/lib/chartmogul/metrics/activity.rb +2 -0
  52. data/lib/chartmogul/metrics/all_key_metrics.rb +2 -0
  53. data/lib/chartmogul/metrics/arpa.rb +2 -0
  54. data/lib/chartmogul/metrics/arr.rb +2 -0
  55. data/lib/chartmogul/metrics/asp.rb +2 -0
  56. data/lib/chartmogul/metrics/base.rb +6 -2
  57. data/lib/chartmogul/metrics/customer_churn_rate.rb +2 -0
  58. data/lib/chartmogul/metrics/customer_count.rb +2 -0
  59. data/lib/chartmogul/metrics/ltv.rb +2 -0
  60. data/lib/chartmogul/metrics/mrr.rb +2 -0
  61. data/lib/chartmogul/metrics/mrr_churn_rate.rb +2 -0
  62. data/lib/chartmogul/metrics/subscription.rb +2 -0
  63. data/lib/chartmogul/object.rb +2 -0
  64. data/lib/chartmogul/ping.rb +2 -0
  65. data/lib/chartmogul/plan.rb +2 -0
  66. data/lib/chartmogul/plan_group.rb +39 -0
  67. data/lib/chartmogul/plan_groups/plans.rb +17 -0
  68. data/lib/chartmogul/resource_path.rb +6 -1
  69. data/lib/chartmogul/subscription.rb +2 -0
  70. data/lib/chartmogul/summary.rb +2 -0
  71. data/lib/chartmogul/transactions/payment.rb +2 -0
  72. data/lib/chartmogul/transactions/refund.rb +2 -0
  73. data/lib/chartmogul/utils/hash_snake_caser.rb +2 -0
  74. data/lib/chartmogul/utils/json_parser.rb +2 -0
  75. data/lib/chartmogul/version.rb +3 -1
  76. metadata +78 -28
@@ -0,0 +1,252 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: post
5
+ uri: https://api.chartmogul.com/v1/data_sources
6
+ body:
7
+ encoding: UTF-8
8
+ string: '{"name":"Data Source #1"}'
9
+ headers:
10
+ User-Agent:
11
+ - Faraday v0.15.4
12
+ Content-Type:
13
+ - application/json
14
+ Authorization:
15
+ - Basic OGIzNjcyOWUzMmU1OWJiMTBlNjEwZWZiOWFhNjExZTA6Nzg0MWEyNWU4Y2VkMmZjOGRmYzFhZGU3YWM0ZmFjZTQ=
16
+ response:
17
+ status:
18
+ code: 201
19
+ message:
20
+ headers:
21
+ server:
22
+ - nginx/1.10.1
23
+ date:
24
+ - Thu, 20 Feb 2020 17:20:15 GMT
25
+ content-type:
26
+ - application/json
27
+ content-length:
28
+ - '152'
29
+ connection:
30
+ - close
31
+ status:
32
+ - 201 Created
33
+ access-control-allow-credentials:
34
+ - 'true'
35
+ body:
36
+ encoding: UTF-8
37
+ string: '{"uuid":"ds_424b9628-5405-11ea-ab18-e3a0f4f45097","name":"Data Source
38
+ #1","system":"Import API","created_at":"2020-02-20T17:20:15.102Z","status":"idle"}'
39
+ http_version:
40
+ recorded_at: Thu, 20 Feb 2020 17:20:15 GMT
41
+ - request:
42
+ method: post
43
+ uri: https://api.chartmogul.com/v1/plans
44
+ body:
45
+ encoding: UTF-8
46
+ string: '{"name":"A Test Plan","interval_count":1,"interval_unit":"month","data_source_uuid":"ds_424b9628-5405-11ea-ab18-e3a0f4f45097"}'
47
+ headers:
48
+ User-Agent:
49
+ - Faraday v0.15.4
50
+ Content-Type:
51
+ - application/json
52
+ Authorization:
53
+ - Basic OGIzNjcyOWUzMmU1OWJiMTBlNjEwZWZiOWFhNjExZTA6Nzg0MWEyNWU4Y2VkMmZjOGRmYzFhZGU3YWM0ZmFjZTQ=
54
+ response:
55
+ status:
56
+ code: 201
57
+ message:
58
+ headers:
59
+ server:
60
+ - nginx/1.10.1
61
+ date:
62
+ - Thu, 20 Feb 2020 17:20:16 GMT
63
+ content-type:
64
+ - application/json; charset=utf-8
65
+ transfer-encoding:
66
+ - chunked
67
+ connection:
68
+ - close
69
+ status:
70
+ - 201 Created
71
+ x-frame-options:
72
+ - SAMEORIGIN
73
+ x-xss-protection:
74
+ - 1; mode=block
75
+ x-content-type-options:
76
+ - nosniff
77
+ etag:
78
+ - W/"de6a4357349f1e696cf670b8cb1d3a91"
79
+ cache-control:
80
+ - max-age=0, private, must-revalidate
81
+ x-request-id:
82
+ - 1d0fbf42-e22c-42ac-b068-3fc78e615d0b
83
+ x-runtime:
84
+ - '0.613620'
85
+ strict-transport-security:
86
+ - max-age=15768000
87
+ body:
88
+ encoding: UTF-8
89
+ string: '{"external_id":"2f7f4360-3633-0138-f01f-62b37fb4c770","name":"A Test
90
+ Plan","interval_count":1,"interval_unit":"month","data_source_uuid":"ds_424b9628-5405-11ea-ab18-e3a0f4f45097","uuid":"pl_2f7f4360-3633-0138-f01f-62b37fb4c770"}'
91
+ http_version:
92
+ recorded_at: Thu, 20 Feb 2020 17:20:16 GMT
93
+ - request:
94
+ method: post
95
+ uri: https://api.chartmogul.com/v1/plans
96
+ body:
97
+ encoding: UTF-8
98
+ string: '{"name":"A another Test Plan","interval_count":1,"interval_unit":"month","data_source_uuid":"ds_424b9628-5405-11ea-ab18-e3a0f4f45097"}'
99
+ headers:
100
+ User-Agent:
101
+ - Faraday v0.15.4
102
+ Content-Type:
103
+ - application/json
104
+ Authorization:
105
+ - Basic OGIzNjcyOWUzMmU1OWJiMTBlNjEwZWZiOWFhNjExZTA6Nzg0MWEyNWU4Y2VkMmZjOGRmYzFhZGU3YWM0ZmFjZTQ=
106
+ response:
107
+ status:
108
+ code: 201
109
+ message:
110
+ headers:
111
+ server:
112
+ - nginx/1.10.1
113
+ date:
114
+ - Thu, 20 Feb 2020 17:20:17 GMT
115
+ content-type:
116
+ - application/json; charset=utf-8
117
+ transfer-encoding:
118
+ - chunked
119
+ connection:
120
+ - close
121
+ status:
122
+ - 201 Created
123
+ x-frame-options:
124
+ - SAMEORIGIN
125
+ x-xss-protection:
126
+ - 1; mode=block
127
+ x-content-type-options:
128
+ - nosniff
129
+ etag:
130
+ - W/"3928a3336f01663683f92bdda358c877"
131
+ cache-control:
132
+ - max-age=0, private, must-revalidate
133
+ x-request-id:
134
+ - 8f90c8e4-8902-4c82-9ac2-b9e466d35b85
135
+ x-runtime:
136
+ - '0.492792'
137
+ strict-transport-security:
138
+ - max-age=15768000
139
+ body:
140
+ encoding: UTF-8
141
+ string: '{"external_id":"3011ead0-3633-0138-f020-62b37fb4c770","name":"A another
142
+ Test Plan","interval_count":1,"interval_unit":"month","data_source_uuid":"ds_424b9628-5405-11ea-ab18-e3a0f4f45097","uuid":"pl_3011ead0-3633-0138-f020-62b37fb4c770"}'
143
+ http_version:
144
+ recorded_at: Thu, 20 Feb 2020 17:20:17 GMT
145
+ - request:
146
+ method: post
147
+ uri: https://api.chartmogul.com/v1/plan_groups
148
+ body:
149
+ encoding: UTF-8
150
+ string: '{"name":"My plan group","plans":["pl_2f7f4360-3633-0138-f01f-62b37fb4c770","pl_3011ead0-3633-0138-f020-62b37fb4c770"]}'
151
+ headers:
152
+ User-Agent:
153
+ - Faraday v0.15.4
154
+ Content-Type:
155
+ - application/json
156
+ Authorization:
157
+ - Basic OGIzNjcyOWUzMmU1OWJiMTBlNjEwZWZiOWFhNjExZTA6Nzg0MWEyNWU4Y2VkMmZjOGRmYzFhZGU3YWM0ZmFjZTQ=
158
+ response:
159
+ status:
160
+ code: 200
161
+ message:
162
+ headers:
163
+ server:
164
+ - nginx/1.10.1
165
+ date:
166
+ - Thu, 20 Feb 2020 17:20:17 GMT
167
+ content-type:
168
+ - application/json; charset=utf-8
169
+ transfer-encoding:
170
+ - chunked
171
+ connection:
172
+ - close
173
+ vary:
174
+ - Accept-Encoding, Accept-Encoding
175
+ status:
176
+ - 200 OK
177
+ x-frame-options:
178
+ - SAMEORIGIN
179
+ x-xss-protection:
180
+ - 1; mode=block
181
+ x-content-type-options:
182
+ - nosniff
183
+ etag:
184
+ - W/"b36573ce415d939f61a58648b6d930cf"
185
+ cache-control:
186
+ - max-age=0, private, must-revalidate
187
+ x-request-id:
188
+ - a48672ef-8c37-459e-ac45-189f0e79c575
189
+ x-runtime:
190
+ - '0.079833'
191
+ strict-transport-security:
192
+ - max-age=15768000
193
+ body:
194
+ encoding: ASCII-8BIT
195
+ string: '{"name":"My plan group","uuid":"plg_f7e7ee61-4cff-47a5-ab45-3127cbfdde0b","plans_count":2}'
196
+ http_version:
197
+ recorded_at: Thu, 20 Feb 2020 17:20:17 GMT
198
+ - request:
199
+ method: get
200
+ uri: https://api.chartmogul.com/v1/plan_groups/plg_f7e7ee61-4cff-47a5-ab45-3127cbfdde0b/plans
201
+ body:
202
+ encoding: US-ASCII
203
+ string: ''
204
+ headers:
205
+ User-Agent:
206
+ - Faraday v0.15.4
207
+ Content-Type:
208
+ - application/json
209
+ Authorization:
210
+ - Basic OGIzNjcyOWUzMmU1OWJiMTBlNjEwZWZiOWFhNjExZTA6Nzg0MWEyNWU4Y2VkMmZjOGRmYzFhZGU3YWM0ZmFjZTQ=
211
+ response:
212
+ status:
213
+ code: 200
214
+ message:
215
+ headers:
216
+ server:
217
+ - nginx/1.10.1
218
+ date:
219
+ - Thu, 20 Feb 2020 17:20:18 GMT
220
+ content-type:
221
+ - application/json; charset=utf-8
222
+ transfer-encoding:
223
+ - chunked
224
+ connection:
225
+ - close
226
+ vary:
227
+ - Accept-Encoding, Accept-Encoding
228
+ status:
229
+ - 200 OK
230
+ x-frame-options:
231
+ - SAMEORIGIN
232
+ x-xss-protection:
233
+ - 1; mode=block
234
+ x-content-type-options:
235
+ - nosniff
236
+ etag:
237
+ - W/"5e8f9b0b2fde5db47f62e9150c0bcdad"
238
+ cache-control:
239
+ - max-age=0, private, must-revalidate
240
+ x-request-id:
241
+ - 58983eb3-fc9a-4d32-8a9f-10e6a0d82a9f
242
+ x-runtime:
243
+ - '0.366925'
244
+ strict-transport-security:
245
+ - max-age=15768000
246
+ body:
247
+ encoding: ASCII-8BIT
248
+ string: '{"plans":[{"name":"A Test Plan","uuid":"pl_2f7f4360-3633-0138-f01f-62b37fb4c770","data_source_uuid":"ds_424b9628-5405-11ea-ab18-e3a0f4f45097","interval_count":1,"interval_unit":"month","external_id":"2f7f4360-3633-0138-f01f-62b37fb4c770"},{"name":"A
249
+ another Test Plan","uuid":"pl_3011ead0-3633-0138-f020-62b37fb4c770","data_source_uuid":"ds_424b9628-5405-11ea-ab18-e3a0f4f45097","interval_count":1,"interval_unit":"month","external_id":"3011ead0-3633-0138-f020-62b37fb4c770"}],"current_page":1,"total_pages":1}'
250
+ http_version:
251
+ recorded_at: Thu, 20 Feb 2020 17:20:18 GMT
252
+ recorded_with: VCR 3.0.3
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'time'
2
4
  require 'json'
3
5
  require 'faraday'
@@ -49,6 +51,8 @@ require 'chartmogul/customer'
49
51
  require 'chartmogul/data_source'
50
52
  require 'chartmogul/ping'
51
53
  require 'chartmogul/plan'
54
+ require 'chartmogul/plan_group'
55
+ require 'chartmogul/plan_groups/plans'
52
56
 
53
57
  require 'chartmogul/metrics/arpa'
54
58
  require 'chartmogul/metrics/arr'
@@ -67,14 +71,17 @@ require 'chartmogul/metrics/subscription'
67
71
  require 'chartmogul/enrichment/customer'
68
72
 
69
73
  module ChartMogul
70
- API_BASE = 'https://api.chartmogul.com'.freeze
74
+ API_BASE = 'https://api.chartmogul.com'
71
75
  MAX_RETRIES = 20
72
76
 
73
77
  class << self
74
78
  extend ConfigAttributes
75
79
 
80
+ CONFIG_THREAD_KEY = 'chartmogul_ruby.config'
81
+
76
82
  def config
77
- @config ||= ChartMogul::Configuration.new
83
+ Thread.current[CONFIG_THREAD_KEY] = ChartMogul::Configuration.new if Thread.current[CONFIG_THREAD_KEY].nil?
84
+ Thread.current[CONFIG_THREAD_KEY]
78
85
  end
79
86
 
80
87
  config_accessor :account_token
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ChartMogul
2
4
  module API
3
5
  module Actions
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ChartMogul
2
4
  module API
3
5
  module Actions
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ChartMogul
2
4
  module API
3
5
  module Actions
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ChartMogul
2
4
  module API
3
5
  module Actions
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ChartMogul
2
4
  module API
3
5
  module Actions
@@ -1,7 +1,13 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ChartMogul
2
4
  module API
3
5
  module Actions
4
6
  module Update
7
+ def self.included(base)
8
+ base.extend ClassMethods
9
+ end
10
+
5
11
  def update!
6
12
  resp = handling_errors do
7
13
  connection.patch("#{resource_path.apply(instance_attributes)}/#{uuid}") do |req|
@@ -13,6 +19,22 @@ module ChartMogul
13
19
 
14
20
  assign_all_attributes(json)
15
21
  end
22
+
23
+ module ClassMethods
24
+ def update!(uuid, attributes = {})
25
+ resource = new(attributes)
26
+
27
+ resp = handling_errors do
28
+ connection.patch("#{resource_path.apply(attributes)}/#{uuid}") do |req|
29
+ req.headers['Content-Type'] = 'application/json'
30
+ req.body = JSON.dump(resource.serialize_for_write)
31
+ end
32
+ end
33
+ json = ChartMogul::Utils::JSONParser.parse(resp.body)
34
+
35
+ new_from_json(json)
36
+ end
37
+ end
16
38
  end
17
39
  end
18
40
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'forwardable'
2
4
 
3
5
  module ChartMogul
@@ -13,6 +15,7 @@ module ChartMogul
13
15
  INTERVAL_RANDOMNESS = 0.5
14
16
  INTERVAL = 1
15
17
  MAX_INTERVAL = 60
18
+ THREAD_CONNECTION_KEY = 'chartmogul_ruby.api_resource.connection'
16
19
 
17
20
  class << self; attr_reader :resource_path, :resource_name, :resource_root_key end
18
21
 
@@ -29,22 +32,15 @@ module ChartMogul
29
32
  end
30
33
 
31
34
  def self.connection
32
- @connection ||= Faraday.new(url: ChartMogul::API_BASE) do |faraday|
33
- faraday.use Faraday::Request::BasicAuthentication, ChartMogul.account_token, ChartMogul.secret_key
34
- faraday.use Faraday::Response::RaiseError
35
- faraday.request :retry, max: ChartMogul.max_retries, retry_statuses: RETRY_STATUSES,
36
- max_interval: MAX_INTERVAL, backoff_factor: BACKOFF_FACTOR,
37
- interval_randomness: INTERVAL_RANDOMNESS, interval: INTERVAL, exceptions: RETRY_EXCEPTIONS
38
- faraday.use Faraday::Adapter::NetHttp
39
- end
35
+ Thread.current[THREAD_CONNECTION_KEY] ||= build_connection
40
36
  end
41
37
 
42
38
  def self.handling_errors
43
39
  yield
44
- rescue Faraday::ClientError => exception
45
- exception.response ? handle_request_error(exception) : handle_other_error(exception)
46
- rescue => exception
47
- handle_other_error(exception)
40
+ rescue Faraday::ClientError => e
41
+ e.response ? handle_request_error(e) : handle_other_error(e)
42
+ rescue StandardError => e
43
+ handle_other_error(e)
48
44
  end
49
45
 
50
46
  def self.handle_request_error(exception)
@@ -80,5 +76,18 @@ module ChartMogul
80
76
  end
81
77
 
82
78
  def_delegators 'self.class', :resource_path, :resource_name, :resource_root_key, :connection, :handling_errors
79
+
80
+ private
81
+
82
+ def self.build_connection
83
+ Faraday.new(url: ChartMogul::API_BASE) do |faraday|
84
+ faraday.use Faraday::Request::BasicAuthentication, ChartMogul.account_token, ChartMogul.secret_key
85
+ faraday.use Faraday::Response::RaiseError
86
+ faraday.request :retry, max: ChartMogul.max_retries, retry_statuses: RETRY_STATUSES,
87
+ max_interval: MAX_INTERVAL, backoff_factor: BACKOFF_FACTOR,
88
+ interval_randomness: INTERVAL_RANDOMNESS, interval: INTERVAL, exceptions: RETRY_EXCEPTIONS
89
+ faraday.use Faraday::Adapter::NetHttp
90
+ end
91
+ end
83
92
  end
84
93
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ChartMogul
2
4
  module Concerns
3
5
  module Entries
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ChartMogul
2
4
  module Concerns
3
5
  module Pageable
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ChartMogul
2
4
  module Concerns
3
5
  module Pageable2
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ChartMogul
2
4
  module Concerns
3
5
  module Summary
@@ -1,14 +1,20 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ChartMogul
2
4
  module ConfigAttributes
3
5
  def config_accessor(attribute, default_value = nil)
4
6
  define_method(attribute) do
5
7
  attr = config.send(attribute) || default_value
6
- raise ConfigurationError, "Configuration for #{attribute} not set" if attr.nil?
8
+ if attr.nil?
9
+ raise ConfigurationError, "Configuration for #{attribute} not set"
10
+ end
11
+
7
12
  attr
8
13
  end
9
14
 
10
15
  define_method("#{attribute}=") do |val|
11
16
  config.send("#{attribute}=", val)
17
+ Thread.current[ChartMogul::APIResource::THREAD_CONNECTION_KEY] = nil
12
18
  end
13
19
  end
14
20
  end