recurly 2.18.21 → 3.0.0.beta.1

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 (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