recurly 2.18.21 → 3.0.0.beta.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (211) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +14 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +5 -0
  5. data/Gemfile +4 -0
  6. data/LICENSE.txt +21 -0
  7. data/README.md +158 -110
  8. data/Rakefile +6 -0
  9. data/bin/bundle +105 -0
  10. data/bin/coderay +29 -0
  11. data/bin/console +14 -0
  12. data/bin/htmldiff +29 -0
  13. data/bin/ldiff +29 -0
  14. data/bin/pry +29 -0
  15. data/bin/rake +29 -0
  16. data/bin/rspec +29 -0
  17. data/bin/setup +8 -0
  18. data/bin/yard +29 -0
  19. data/bin/yardoc +29 -0
  20. data/bin/yri +29 -0
  21. data/lib/data/ca-certificates.crt +31 -0
  22. data/lib/recurly/client/operations.rb +935 -0
  23. data/lib/recurly/client.rb +198 -0
  24. data/lib/recurly/errors/api_errors.rb +35 -0
  25. data/lib/recurly/errors/network_errors.rb +8 -0
  26. data/lib/recurly/errors.rb +34 -0
  27. data/lib/recurly/pager.rb +119 -0
  28. data/lib/recurly/request.rb +30 -0
  29. data/lib/recurly/requests/account_acquisition_updatable.rb +22 -0
  30. data/lib/recurly/requests/account_create_only.rb +18 -0
  31. data/lib/recurly/requests/account_updatable.rb +50 -0
  32. data/lib/recurly/requests/add_on_create.rb +38 -0
  33. data/lib/recurly/requests/add_on_update.rb +38 -0
  34. data/lib/recurly/requests/address.rb +42 -0
  35. data/lib/recurly/requests/billing_info_create.rb +58 -0
  36. data/lib/recurly/requests/coupon_create_only.rb +66 -0
  37. data/lib/recurly/requests/coupon_updatable.rb +30 -0
  38. data/lib/recurly/requests/create_account.rb +62 -0
  39. data/lib/recurly/requests/create_coupon.rb +90 -0
  40. data/lib/recurly/requests/invoice_create.rb +42 -0
  41. data/lib/recurly/requests/invoice_refund.rb +30 -0
  42. data/lib/recurly/requests/line_item_create.rb +46 -0
  43. data/lib/recurly/requests/plan_create.rb +66 -0
  44. data/lib/recurly/requests/plan_update.rb +70 -0
  45. data/lib/recurly/requests/shipping_address_create.rb +58 -0
  46. data/lib/recurly/requests/shipping_address_update.rb +62 -0
  47. data/lib/recurly/requests/subscription_add_on_create.rb +22 -0
  48. data/lib/recurly/requests/subscription_change_create.rb +42 -0
  49. data/lib/recurly/requests/subscription_create.rb +86 -0
  50. data/lib/recurly/requests/subscription_update.rb +42 -0
  51. data/lib/recurly/requests/update_coupon.rb +30 -0
  52. data/lib/recurly/resource.rb +16 -1103
  53. data/lib/recurly/resources/account.rb +86 -0
  54. data/lib/recurly/resources/account_acquisition.rb +42 -0
  55. data/lib/recurly/resources/account_balance.rb +22 -0
  56. data/lib/recurly/resources/account_note.rb +30 -0
  57. data/lib/recurly/resources/add_on.rb +62 -0
  58. data/lib/recurly/resources/address.rb +42 -0
  59. data/lib/recurly/resources/billing_info.rb +62 -0
  60. data/lib/recurly/resources/coupon.rb +110 -0
  61. data/lib/recurly/resources/coupon_discount.rb +22 -0
  62. data/lib/recurly/resources/coupon_redemption.rb +46 -0
  63. data/lib/recurly/resources/credit_payment.rb +62 -0
  64. data/lib/recurly/resources/error.rb +18 -0
  65. data/lib/recurly/resources/error_may_have_transaction.rb +22 -0
  66. data/lib/recurly/resources/invoice.rb +138 -0
  67. data/lib/recurly/resources/invoice_collection.rb +18 -0
  68. data/lib/recurly/resources/line_item.rb +166 -0
  69. data/lib/recurly/resources/plan.rb +86 -0
  70. data/lib/recurly/resources/settings.rb +18 -0
  71. data/lib/recurly/resources/shipping_address.rb +74 -0
  72. data/lib/recurly/resources/site.rb +46 -0
  73. data/lib/recurly/resources/subscription.rb +134 -0
  74. data/lib/recurly/resources/subscription_add_on.rb +42 -0
  75. data/lib/recurly/resources/subscription_change.rb +54 -0
  76. data/lib/recurly/resources/tax_info.rb +18 -0
  77. data/lib/recurly/resources/transaction.rb +146 -0
  78. data/lib/recurly/resources/unique_coupon_code.rb +38 -0
  79. data/lib/recurly/resources/user.rb +38 -0
  80. data/lib/recurly/schema/json_deserializer.rb +53 -0
  81. data/lib/recurly/schema/json_parser.rb +71 -0
  82. data/lib/recurly/schema/request_caster.rb +66 -0
  83. data/lib/recurly/schema/schema_factory.rb +50 -0
  84. data/lib/recurly/schema/schema_validator.rb +125 -0
  85. data/lib/recurly/schema.rb +114 -0
  86. data/lib/recurly/version.rb +1 -10
  87. data/lib/recurly.rb +14 -145
  88. data/recurly.gemspec +32 -0
  89. data/scripts/build +4 -0
  90. data/scripts/clean +6 -0
  91. data/scripts/test +3 -0
  92. metadata +129 -173
  93. data/lib/recurly/account.rb +0 -209
  94. data/lib/recurly/account_acquisition.rb +0 -27
  95. data/lib/recurly/account_balance.rb +0 -21
  96. data/lib/recurly/add_on.rb +0 -46
  97. data/lib/recurly/address.rb +0 -25
  98. data/lib/recurly/adjustment.rb +0 -81
  99. data/lib/recurly/api/errors.rb +0 -208
  100. data/lib/recurly/api/net_http_adapter.rb +0 -111
  101. data/lib/recurly/api.rb +0 -110
  102. data/lib/recurly/billing_info.rb +0 -113
  103. data/lib/recurly/coupon.rb +0 -136
  104. data/lib/recurly/credit_payment.rb +0 -32
  105. data/lib/recurly/custom_field.rb +0 -15
  106. data/lib/recurly/delivery.rb +0 -19
  107. data/lib/recurly/error.rb +0 -13
  108. data/lib/recurly/gift_card.rb +0 -85
  109. data/lib/recurly/helper.rb +0 -51
  110. data/lib/recurly/invoice.rb +0 -304
  111. data/lib/recurly/invoice_collection.rb +0 -14
  112. data/lib/recurly/item.rb +0 -36
  113. data/lib/recurly/js.rb +0 -14
  114. data/lib/recurly/juris_detail.rb +0 -15
  115. data/lib/recurly/measured_unit.rb +0 -16
  116. data/lib/recurly/money.rb +0 -120
  117. data/lib/recurly/note.rb +0 -14
  118. data/lib/recurly/plan.rb +0 -43
  119. data/lib/recurly/purchase.rb +0 -238
  120. data/lib/recurly/redemption.rb +0 -46
  121. data/lib/recurly/resource/association.rb +0 -16
  122. data/lib/recurly/resource/errors.rb +0 -20
  123. data/lib/recurly/resource/pager.rb +0 -313
  124. data/lib/recurly/shipping_address.rb +0 -26
  125. data/lib/recurly/shipping_fee.rb +0 -17
  126. data/lib/recurly/shipping_method.rb +0 -13
  127. data/lib/recurly/subscription/add_ons.rb +0 -82
  128. data/lib/recurly/subscription.rb +0 -366
  129. data/lib/recurly/subscription_add_on.rb +0 -58
  130. data/lib/recurly/tax_detail.rb +0 -18
  131. data/lib/recurly/tax_type.rb +0 -13
  132. data/lib/recurly/tier.rb +0 -18
  133. data/lib/recurly/transaction/errors.rb +0 -115
  134. data/lib/recurly/transaction.rb +0 -131
  135. data/lib/recurly/usage.rb +0 -28
  136. data/lib/recurly/verify.rb +0 -12
  137. data/lib/recurly/webhook/account_notification.rb +0 -13
  138. data/lib/recurly/webhook/billing_info_update_failed_notification.rb +0 -6
  139. data/lib/recurly/webhook/billing_info_updated_notification.rb +0 -6
  140. data/lib/recurly/webhook/canceled_account_notification.rb +0 -6
  141. data/lib/recurly/webhook/canceled_gift_card_notification.rb +0 -6
  142. data/lib/recurly/webhook/canceled_subscription_notification.rb +0 -6
  143. data/lib/recurly/webhook/closed_credit_invoice_notification.rb +0 -6
  144. data/lib/recurly/webhook/closed_invoice_notification.rb +0 -6
  145. data/lib/recurly/webhook/credit_payment_notification.rb +0 -12
  146. data/lib/recurly/webhook/deactivated_item_notification.rb +0 -6
  147. data/lib/recurly/webhook/deleted_shipping_address_notification.rb +0 -6
  148. data/lib/recurly/webhook/dunning_notification.rb +0 -14
  149. data/lib/recurly/webhook/expired_subscription_notification.rb +0 -6
  150. data/lib/recurly/webhook/failed_charge_invoice_notification.rb +0 -6
  151. data/lib/recurly/webhook/failed_payment_notification.rb +0 -6
  152. data/lib/recurly/webhook/fraud_info_updated_notification.rb +0 -6
  153. data/lib/recurly/webhook/gift_card_notification.rb +0 -8
  154. data/lib/recurly/webhook/invoice_notification.rb +0 -12
  155. data/lib/recurly/webhook/item_notification.rb +0 -7
  156. data/lib/recurly/webhook/low_balance_gift_card_notification.rb +0 -6
  157. data/lib/recurly/webhook/new_account_notification.rb +0 -6
  158. data/lib/recurly/webhook/new_charge_invoice_notification.rb +0 -6
  159. data/lib/recurly/webhook/new_credit_invoice_notification.rb +0 -6
  160. data/lib/recurly/webhook/new_credit_payment_notification.rb +0 -6
  161. data/lib/recurly/webhook/new_dunning_event_notification.rb +0 -6
  162. data/lib/recurly/webhook/new_invoice_notification.rb +0 -6
  163. data/lib/recurly/webhook/new_item_notification.rb +0 -6
  164. data/lib/recurly/webhook/new_shipping_address_notification.rb +0 -6
  165. data/lib/recurly/webhook/new_subscription_notification.rb +0 -6
  166. data/lib/recurly/webhook/new_usage_notification.rb +0 -8
  167. data/lib/recurly/webhook/notification.rb +0 -18
  168. data/lib/recurly/webhook/paid_charge_invoice_notification.rb +0 -6
  169. data/lib/recurly/webhook/past_due_charge_invoice_notification.rb +0 -6
  170. data/lib/recurly/webhook/past_due_invoice_notification.rb +0 -6
  171. data/lib/recurly/webhook/paused_subscription_renewal_notification.rb +0 -6
  172. data/lib/recurly/webhook/prerenewal_notification.rb +0 -6
  173. data/lib/recurly/webhook/processing_charge_invoice_notification.rb +0 -6
  174. data/lib/recurly/webhook/processing_credit_invoice_notification.rb +0 -6
  175. data/lib/recurly/webhook/processing_invoice_notification.rb +0 -6
  176. data/lib/recurly/webhook/processing_payment_notification.rb +0 -6
  177. data/lib/recurly/webhook/purchased_gift_card_notification.rb +0 -7
  178. data/lib/recurly/webhook/reactivated_account_notification.rb +0 -6
  179. data/lib/recurly/webhook/reactivated_item_notification.rb +0 -6
  180. data/lib/recurly/webhook/redeemed_gift_card_notification.rb +0 -7
  181. data/lib/recurly/webhook/regenerated_gift_card_notification.rb +0 -6
  182. data/lib/recurly/webhook/renewed_subscription_notification.rb +0 -6
  183. data/lib/recurly/webhook/reopened_charge_invoice_notification.rb +0 -6
  184. data/lib/recurly/webhook/reopened_credit_invoice_notification.rb +0 -6
  185. data/lib/recurly/webhook/scheduled_payment_notification.rb +0 -6
  186. data/lib/recurly/webhook/scheduled_subscription_pause_notification.rb +0 -6
  187. data/lib/recurly/webhook/scheduled_subscription_update_notification.rb +0 -6
  188. data/lib/recurly/webhook/subscription_notification.rb +0 -12
  189. data/lib/recurly/webhook/subscription_pause_canceled_notification.rb +0 -6
  190. data/lib/recurly/webhook/subscription_pause_modified_notification.rb +0 -6
  191. data/lib/recurly/webhook/subscription_paused_notification.rb +0 -6
  192. data/lib/recurly/webhook/subscription_resumed_notification.rb +0 -6
  193. data/lib/recurly/webhook/successful_payment_notification.rb +0 -6
  194. data/lib/recurly/webhook/successful_refund_notification.rb +0 -6
  195. data/lib/recurly/webhook/transaction_authorized_notification.rb +0 -6
  196. data/lib/recurly/webhook/transaction_notification.rb +0 -12
  197. data/lib/recurly/webhook/transaction_status_updated_notification.rb +0 -6
  198. data/lib/recurly/webhook/updated_account_notification.rb +0 -6
  199. data/lib/recurly/webhook/updated_balance_gift_card_notification.rb +0 -7
  200. data/lib/recurly/webhook/updated_gift_card_notification.rb +0 -6
  201. data/lib/recurly/webhook/updated_invoice_notification.rb +0 -6
  202. data/lib/recurly/webhook/updated_item_notification.rb +0 -6
  203. data/lib/recurly/webhook/updated_shipping_address_notification.rb +0 -6
  204. data/lib/recurly/webhook/updated_subscription_notification.rb +0 -6
  205. data/lib/recurly/webhook/void_payment_notification.rb +0 -6
  206. data/lib/recurly/webhook/voided_credit_invoice_notification.rb +0 -6
  207. data/lib/recurly/webhook/voided_credit_payment_notification.rb +0 -6
  208. data/lib/recurly/webhook.rb +0 -113
  209. data/lib/recurly/xml/nokogiri.rb +0 -60
  210. data/lib/recurly/xml/rexml.rb +0 -52
  211. data/lib/recurly/xml.rb +0 -122
@@ -0,0 +1,198 @@
1
+ require 'faraday'
2
+ require 'logger'
3
+ require_relative './schema/json_parser'
4
+
5
+ module Recurly
6
+ class Client
7
+ require_relative './client/operations'
8
+
9
+ BASE_URL = "https://partner-api.recurly.com/"
10
+
11
+ # The last result of the *X-RateLimit-Limit* header
12
+ # @return [Integer] The rate limit applied to this client.
13
+ attr_reader :rate_limit
14
+
15
+ # The last result of the *X-RateLimit-Remaining* header
16
+ # @return [Integer] The number of remaining requests, decrements per request.
17
+ attr_reader :rate_limit_remaining
18
+
19
+ # The last result of the *X-RateLimit-Reset* header
20
+ # @return [DateTime] The DateTime in which the request count will be reset.
21
+ attr_reader :rate_limit_reset
22
+
23
+ # Initialize a client. It requires an API key.
24
+ #
25
+ # @example
26
+ # API_KEY = '83749879bbde395b5fe0cc1a5abf8e5'
27
+ # SITE_ID = 'dqzlv9shi7wa'
28
+ # client = Recurly::Client.new(site_id: SITE_ID, api_key: API_KEY)
29
+ # # You can optionally use the subdomain instead of the site id
30
+ # client = Recurly::Client.new(subdomain: 'mysite-prod', api_key: API_KEY)
31
+ # sub = client.get_subscription(subscription_id: 'abcd123456')
32
+ # @example
33
+ # # You can also pass the initializer a block. This will give you
34
+ # # a client scoped for just that block
35
+ # Recurly::Client.new(subdomain: 'mysite-prod', api_key: API_KEY) do |client|
36
+ # sub = client.get_subscription(subscription_id: 'abcd123456')
37
+ # end
38
+ # @example
39
+ # # If you only plan on using the client for more than one site,
40
+ # # you should initialize a new client for each site.
41
+ #
42
+ # # Give a `site_id`
43
+ # client = Recurly::Client.new(api_key: API_KEY, site_id: SITE_ID)
44
+ # # Or use the subdomain
45
+ # client = Recurly::Client.new(api_key: API_KEY, subdomain: 'mysite-dev')
46
+ #
47
+ # sub = client.get_subscription(subscription_id: 'abcd123456')
48
+ #
49
+ # # you should create a new client to connect to another site
50
+ # client = Recurly::Client.new(api_key: API_KEY, subdomain: 'mysite-prod')
51
+ # sub = client.get_subscription(subscription_id: 'abcd7890')
52
+ #
53
+ # @param api_key [String] The private API key
54
+ # @param site_id [String] The site you wish to be scoped to.
55
+ # @param subdomain [String] Optional subdomain for the site you wish to be scoped to. Providing this makes all the `site_id` parameters optional.
56
+ def initialize(api_key:, site_id: nil, subdomain: nil, **options)
57
+ if site_id
58
+ @site_id = site_id
59
+ elsif subdomain
60
+ @site_id = "subdomain-#{subdomain}"
61
+ else
62
+ raise ArgumentError, "You must pass a site_id or subdomain argument to initialize the Client"
63
+ end
64
+
65
+ @log_level = options[:log_level] || Logger::WARN
66
+ @logger = Logger.new(STDOUT)
67
+ @logger.level = @log_level
68
+
69
+ @conn = Faraday.new(url: BASE_URL) do |faraday|
70
+ if @log_level == Logger::INFO
71
+ faraday.response :logger
72
+ end
73
+ faraday.basic_auth(api_key, '')
74
+ faraday.adapter :net_http do |http| # yields Net::HTTP
75
+ # Let's not use the bundled cert in production yet
76
+ # but we will use these certs for any other staging or dev environment
77
+ unless BASE_URL.end_with?('.recurly.com')
78
+ http.ca_file = File.join(File.dirname(__FILE__), '../data/ca-certificates.crt')
79
+ end
80
+ http.use_ssl = true
81
+ http.verify_mode = OpenSSL::SSL::VERIFY_PEER
82
+ http.open_timeout = 50
83
+ http.read_timeout = 60
84
+ http.keep_alive_timeout = 60
85
+ end
86
+ end
87
+
88
+ # TODO this is undocumented until we finalize it
89
+ @extra_headers = options[:headers] || {}
90
+
91
+ # execute block with this client if given
92
+ yield(self) if block_given?
93
+ end
94
+
95
+ def next_page(pager)
96
+ run_request(:get, pager.next, nil, headers)
97
+ end
98
+
99
+ protected
100
+
101
+ def pager(path, **options)
102
+ Pager.new(client: self, path: path, options: options)
103
+ end
104
+
105
+ def get(path, **options)
106
+ response = run_request(:get, path, options.compact, headers)
107
+ raise_api_error!(response) if response.status != 200
108
+ JSONParser.parse(self, response.body)
109
+ rescue Faraday::ClientError => ex
110
+ raise_network_error!(ex)
111
+ end
112
+
113
+ def post(path, request_data, request_class, **options)
114
+ request = request_class.new(request_data)
115
+ request.validate!
116
+ logger.info("POST BODY #{JSON.dump(request_data)}")
117
+ response = run_request(:post, path, JSON.dump(request.attributes), headers)
118
+ raise_api_error!(response) if response.status != 201
119
+ JSONParser.parse(self, response.body)
120
+ rescue Faraday::ClientError => ex
121
+ raise_network_error!(ex)
122
+ end
123
+
124
+ def put(path, request_data, request_class, **options)
125
+ request = request_class.new(request_data)
126
+ request.validate!
127
+ logger.info("PUT BODY #{JSON.dump(request_data)}")
128
+ response = run_request(:put, path, JSON.dump(request_data), headers)
129
+ raise_api_error!(response) if ![200, 201].include?(response.status)
130
+ JSONParser.parse(self, response.body)
131
+ rescue Faraday::ClientError => ex
132
+ raise_network_error!(ex)
133
+ end
134
+
135
+ def delete(path, **options)
136
+ response = run_request(:delete, path, options.compact, headers)
137
+ raise_api_error!(response) if ![200, 201].include?(response.status)
138
+ JSONParser.parse(self, response.body)
139
+ rescue Faraday::ClientError => ex
140
+ raise_network_error!(ex)
141
+ end
142
+
143
+ protected
144
+
145
+ # Used by the operations.rb file to interpolate paths
146
+ attr_reader :site_id
147
+
148
+ private
149
+
150
+ # @return [Logger]
151
+ attr_reader :logger
152
+
153
+ def run_request(method, url, body, headers)
154
+ read_headers @conn.run_request(method, url, body, headers)
155
+ end
156
+
157
+ def raise_network_error!(ex)
158
+ error_class = case ex
159
+ when Faraday::TimeoutError
160
+ Errors::TimeoutError
161
+ when Faraday::ConnectionFailed
162
+ Errors::ConnectionFailed
163
+ when Faraday::SSLError
164
+ Errors::SSLError
165
+ else
166
+ Errors::NetworkError
167
+ end
168
+
169
+ raise error_class, ex.message
170
+ end
171
+
172
+ def raise_api_error!(response)
173
+ error = JSONParser.parse(self, response.body)
174
+ error_class = Errors::APIError.error_class(error.type)
175
+ raise error_class.new(response, error)
176
+ end
177
+
178
+ def read_headers(response)
179
+ @rate_limit = response.headers['x-ratelimit-limit'].to_i
180
+ @rate_limit_remaining = response.headers['x-ratelimit-remaining'].to_i
181
+ @rate_limit_reset = Time.at(response.headers['x-ratelimit-reset'].to_i).to_datetime
182
+ response
183
+ end
184
+
185
+ def headers
186
+ {
187
+ 'Accept' => "application/vnd.recurly.#{api_version}", # got this method from operations.rb
188
+ 'Content-Type' => 'application/json',
189
+ 'User-Agent' => "Recurly/#{VERSION}; #{RUBY_DESCRIPTION}"
190
+ }.merge(@extra_headers)
191
+ end
192
+
193
+ def interpolate_path(path, **options)
194
+ path = path.gsub("{", "%{")
195
+ path % options
196
+ end
197
+ end
198
+ end
@@ -0,0 +1,35 @@
1
+ module Recurly
2
+ module Errors
3
+ class BadRequestError < Errors::APIError; end
4
+
5
+ class InternalServerError < Errors::APIError; end
6
+
7
+ class ImmutableSubscriptionError < Errors::APIError; end
8
+
9
+ class InvalidApiKeyError < Errors::APIError; end
10
+
11
+ class InvalidApiVersionError < Errors::APIError; end
12
+
13
+ class InvalidContentTypeError < Errors::APIError; end
14
+
15
+ class InvalidPermissionsError < Errors::APIError; end
16
+
17
+ class InvalidTokenError < Errors::APIError; end
18
+
19
+ class NotFoundError < Errors::APIError; end
20
+
21
+ class SimultaneousRequestError < Errors::APIError; end
22
+
23
+ class TransactionError < Errors::APIError; end
24
+
25
+ class UnauthorizedError < Errors::APIError; end
26
+
27
+ class UnavailableInApiVersionError < Errors::APIError; end
28
+
29
+ class UnknownApiVersionError < Errors::APIError; end
30
+
31
+ class ValidationError < Errors::APIError; end
32
+
33
+ class MissingFeatureError < Errors::APIError; end
34
+ end
35
+ end
@@ -0,0 +1,8 @@
1
+ module Recurly
2
+ module Errors
3
+ class NetworkError < StandardError; end
4
+ class TimeoutError < NetworkError; end
5
+ class ConnectionFailed < NetworkError; end
6
+ class SSLError < NetworkError; end
7
+ end
8
+ end
@@ -0,0 +1,34 @@
1
+ module Recurly
2
+ module Errors
3
+ class APIError < StandardError
4
+ # @!attribute recurly_error
5
+ # @return [Recurly::Resources::Error] The {Recurly::Resources::Error} object
6
+ attr_reader :recurly_error
7
+
8
+ # Looks up an Error class by name
9
+ # @example
10
+ # Errors.error_class('BadRequestError')
11
+ # #=> Errors::BadRequestError
12
+ # @param error_key [String]
13
+ # @return [Errors::APIError,Errors::NetworkError]
14
+ def self.error_class(error_key)
15
+ class_name = error_key.split('_').map(&:capitalize).join
16
+ class_name += "Error" unless class_name.end_with?("Error")
17
+ Errors.const_get(class_name)
18
+ end
19
+
20
+ def initialize(response, error)
21
+ super("#{self.class.name}: #{error.message}")
22
+ @response = response
23
+ @recurly_error = error
24
+ end
25
+
26
+ def status_code
27
+ @response.status
28
+ end
29
+ end
30
+ end
31
+
32
+ require_relative "./errors/api_errors"
33
+ require_relative "./errors/network_errors"
34
+ end
@@ -0,0 +1,119 @@
1
+ module Recurly
2
+ class Pager
3
+ attr_accessor :client
4
+ attr_reader :data, :next
5
+
6
+ def initialize(client:, path:, options: {})
7
+ @client = client
8
+ @path = path
9
+ @options = options
10
+ @next = build_path(@path, @options)
11
+ end
12
+
13
+ # Enumerates each "page" from the server.
14
+ # This method yields a given block with the array of items
15
+ # in the page `data` and the page number the pagination is on
16
+ # `page_num` which is 0-indexed.
17
+ #
18
+ # @example
19
+ # plans = client.list_plans()
20
+ # plans.each_page do |data|
21
+ # data.each do |plan|
22
+ # puts "Plan: #{plan.id}"
23
+ # end
24
+ # end
25
+ # @example
26
+ # plans = client.list_plans()
27
+ # plans.each_page.each_with_index do |data, page_num|
28
+ # puts "Page Number: #{page_num}"
29
+ # data.each do |plan|
30
+ # puts "Plan: #{plan.id}"
31
+ # end
32
+ # end
33
+ def each_page(&block)
34
+ if block_given?
35
+ page_enumerator.each(&block)
36
+ else
37
+ page_enumerator
38
+ end
39
+ end
40
+
41
+ # Enumerates each item on the server. Each item is yielded to the
42
+ # block presenting the effect of a continuous stream of items.
43
+ # In reality, the pager is fetching blocks of data (pages) under the hood.
44
+ # This method yields a given block with the next item to process.
45
+ #
46
+ # @example
47
+ # plans = client.list_plans()
48
+ # plans.each do |plan|
49
+ # puts "Plan: #{plan.id}"
50
+ # end
51
+ # @example
52
+ # plans = client.list_plans()
53
+ # plans.each.each_with_index do |plan, idx|
54
+ # puts "Plan #{idx}: #{plan.id}"
55
+ # end
56
+ def each(&block)
57
+ if block_given?
58
+ item_enumerator.each(&block)
59
+ else
60
+ item_enumerator
61
+ end
62
+ end
63
+
64
+ def has_more?
65
+ !!@has_more
66
+ end
67
+
68
+ def requires_client?
69
+ true
70
+ end
71
+
72
+ private
73
+
74
+ def from_json(data)
75
+ @data = data['data'].map do |resource_data|
76
+ JSONParser.from_json(resource_data)
77
+ end
78
+ @next = data['next']
79
+ @has_more = data['has_more']
80
+ end
81
+
82
+ def item_enumerator
83
+ Enumerator.new do |yielder|
84
+ page_enumerator.each do |data|
85
+ data.each do |item|
86
+ yielder << item
87
+ end
88
+ end
89
+ end
90
+ end
91
+
92
+ def page_enumerator
93
+ Enumerator.new do |yielder|
94
+ loop do
95
+ fetch_next!
96
+ yielder << data
97
+ unless has_more?
98
+ rewind!
99
+ break
100
+ end
101
+ end
102
+ end
103
+ end
104
+
105
+ def fetch_next!
106
+ response = @client.next_page(self)
107
+ from_json(JSON.parse(response.body))
108
+ end
109
+
110
+ def rewind!
111
+ @data = []
112
+ @next = build_path(@path, @options)
113
+ end
114
+
115
+ def build_path(path, options)
116
+ "#{path}?#{URI.encode_www_form(options)}"
117
+ end
118
+ end
119
+ end
@@ -0,0 +1,30 @@
1
+ module Recurly
2
+ # This class represents a request to Recurly.
3
+ # It's used to validate requests data as well as
4
+ # cast and serialize the request data to JSON.
5
+ class Request
6
+ extend Schema::SchemaFactory
7
+ extend Schema::RequestCaster
8
+ include Schema::SchemaValidator
9
+
10
+ attr_reader :attributes
11
+
12
+ def ==(other_resource)
13
+ self.attributes == other_resource.attributes
14
+ end
15
+
16
+ protected
17
+
18
+ def initialize(attributes = {})
19
+ @attributes = self.class.cast(attributes.clone)
20
+ end
21
+
22
+ def to_s
23
+ self.inspect
24
+ end
25
+
26
+ def schema
27
+ self.class.schema
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,22 @@
1
+ module Recurly
2
+ module Requests
3
+ class AccountAcquisitionUpdatable < Request
4
+
5
+ # @!attribute campaign
6
+ # @return [String] An arbitrary identifier for the marketing campaign that led to the acquisition of this account.
7
+ define_attribute :campaign, String
8
+
9
+ # @!attribute channel
10
+ # @return [String] The channel through which the account was acquired.
11
+ define_attribute :channel, String, {:enum => ["referral", "social_media", "email", "paid_search", "organic_search", "direct_traffic", "marketing_content", "blog", "events", "outbound_sales", "advertising", "public_relations", "other"]}
12
+
13
+ # @!attribute cost
14
+ # @return [Hash] Account balance
15
+ define_attribute :cost, Hash
16
+
17
+ # @!attribute subchannel
18
+ # @return [String] An arbitrary subchannel string representing a distinction/subcategory within a broader channel.
19
+ define_attribute :subchannel, String
20
+ end
21
+ end
22
+ end