recurly 2.17.0 → 3.14.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (260) hide show
  1. checksums.yaml +4 -4
  2. data/.bumpversion.cfg +15 -0
  3. data/.github/ISSUE_TEMPLATE/bug-report.md +30 -0
  4. data/.github/ISSUE_TEMPLATE/question-or-other.md +10 -0
  5. data/.github/workflows/docs.yml +28 -0
  6. data/.github_changelog_generator +8 -0
  7. data/.gitignore +15 -0
  8. data/.rspec +2 -0
  9. data/.travis.yml +13 -0
  10. data/.yardopts +2 -0
  11. data/CHANGELOG.md +313 -0
  12. data/CODE_OF_CONDUCT.md +130 -0
  13. data/CONTRIBUTING.md +106 -0
  14. data/GETTING_STARTED.md +319 -0
  15. data/Gemfile +4 -0
  16. data/LICENSE.txt +21 -0
  17. data/README.md +9 -153
  18. data/Rakefile +6 -0
  19. data/benchmark.rb +16 -0
  20. data/lib/data/ca-certificates.crt +3466 -0
  21. data/lib/recurly/client/operations.rb +3665 -0
  22. data/lib/recurly/client.rb +353 -0
  23. data/lib/recurly/connection_pool.rb +40 -0
  24. data/lib/recurly/errors/api_errors.rb +83 -0
  25. data/lib/recurly/errors/network_errors.rb +10 -0
  26. data/lib/recurly/errors.rb +68 -0
  27. data/lib/recurly/http.rb +50 -0
  28. data/lib/recurly/pager.rb +146 -0
  29. data/lib/recurly/request.rb +31 -0
  30. data/lib/recurly/requests/account_acquisition_cost.rb +18 -0
  31. data/lib/recurly/requests/account_acquisition_updatable.rb +26 -0
  32. data/lib/recurly/requests/account_create.rb +90 -0
  33. data/lib/recurly/requests/account_purchase.rb +90 -0
  34. data/lib/recurly/requests/account_update.rb +78 -0
  35. data/lib/recurly/requests/add_on_create.rb +94 -0
  36. data/lib/recurly/requests/add_on_pricing.rb +18 -0
  37. data/lib/recurly/requests/add_on_update.rb +74 -0
  38. data/lib/recurly/requests/address.rb +46 -0
  39. data/lib/recurly/requests/billing_info_create.rb +110 -0
  40. data/lib/recurly/requests/coupon_bulk_create.rb +14 -0
  41. data/lib/recurly/requests/coupon_create.rb +94 -0
  42. data/lib/recurly/requests/coupon_pricing.rb +18 -0
  43. data/lib/recurly/requests/coupon_redemption_create.rb +18 -0
  44. data/lib/recurly/requests/coupon_update.rb +34 -0
  45. data/lib/recurly/requests/custom_field.rb +18 -0
  46. data/lib/recurly/requests/external_refund.rb +22 -0
  47. data/lib/recurly/requests/external_transaction.rb +26 -0
  48. data/lib/recurly/requests/invoice_address.rb +54 -0
  49. data/lib/recurly/requests/invoice_collect.rb +18 -0
  50. data/lib/recurly/requests/invoice_create.rb +42 -0
  51. data/lib/recurly/requests/invoice_refund.rb +34 -0
  52. data/lib/recurly/requests/invoice_updatable.rb +34 -0
  53. data/lib/recurly/requests/item_create.rb +58 -0
  54. data/lib/recurly/requests/item_update.rb +58 -0
  55. data/lib/recurly/requests/line_item_create.rb +82 -0
  56. data/lib/recurly/requests/line_item_refund.rb +22 -0
  57. data/lib/recurly/requests/measured_unit_create.rb +22 -0
  58. data/lib/recurly/requests/measured_unit_update.rb +22 -0
  59. data/lib/recurly/requests/plan_create.rb +98 -0
  60. data/lib/recurly/requests/plan_hosted_pages.rb +26 -0
  61. data/lib/recurly/requests/plan_pricing.rb +22 -0
  62. data/lib/recurly/requests/plan_update.rb +94 -0
  63. data/lib/recurly/requests/pricing.rb +18 -0
  64. data/lib/recurly/requests/purchase_create.rb +74 -0
  65. data/lib/recurly/requests/shipping_address_create.rb +62 -0
  66. data/lib/recurly/requests/shipping_address_update.rb +66 -0
  67. data/lib/recurly/requests/shipping_fee_create.rb +22 -0
  68. data/lib/recurly/requests/shipping_method_create.rb +26 -0
  69. data/lib/recurly/requests/shipping_method_update.rb +26 -0
  70. data/lib/recurly/requests/shipping_purchase.rb +22 -0
  71. data/lib/recurly/requests/subscription_add_on_create.rb +38 -0
  72. data/lib/recurly/requests/subscription_add_on_tier.rb +18 -0
  73. data/lib/recurly/requests/subscription_add_on_update.rb +42 -0
  74. data/lib/recurly/requests/subscription_cancel.rb +14 -0
  75. data/lib/recurly/requests/subscription_change_create.rb +66 -0
  76. data/lib/recurly/requests/subscription_change_shipping_create.rb +22 -0
  77. data/lib/recurly/requests/subscription_create.rb +106 -0
  78. data/lib/recurly/requests/subscription_pause.rb +14 -0
  79. data/lib/recurly/requests/subscription_purchase.rb +66 -0
  80. data/lib/recurly/requests/subscription_shipping_create.rb +30 -0
  81. data/lib/recurly/requests/subscription_shipping_purchase.rb +22 -0
  82. data/lib/recurly/requests/subscription_shipping_update.rb +22 -0
  83. data/lib/recurly/requests/subscription_update.rb +58 -0
  84. data/lib/recurly/requests/tier.rb +18 -0
  85. data/lib/recurly/requests/usage_create.rb +26 -0
  86. data/lib/recurly/requests.rb +8 -0
  87. data/lib/recurly/resource.rb +23 -1082
  88. data/lib/recurly/resources/account.rb +130 -0
  89. data/lib/recurly/resources/account_acquisition.rb +46 -0
  90. data/lib/recurly/resources/account_acquisition_cost.rb +18 -0
  91. data/lib/recurly/resources/account_balance.rb +26 -0
  92. data/lib/recurly/resources/account_balance_amount.rb +18 -0
  93. data/lib/recurly/resources/account_mini.rb +46 -0
  94. data/lib/recurly/resources/account_note.rb +34 -0
  95. data/lib/recurly/resources/add_on.rb +114 -0
  96. data/lib/recurly/resources/add_on_mini.rb +54 -0
  97. data/lib/recurly/resources/add_on_pricing.rb +18 -0
  98. data/lib/recurly/resources/address.rb +46 -0
  99. data/lib/recurly/resources/billing_info.rb +66 -0
  100. data/lib/recurly/resources/billing_info_updated_by.rb +18 -0
  101. data/lib/recurly/resources/binary_file.rb +14 -0
  102. data/lib/recurly/resources/coupon.rb +130 -0
  103. data/lib/recurly/resources/coupon_discount.rb +26 -0
  104. data/lib/recurly/resources/coupon_discount_pricing.rb +18 -0
  105. data/lib/recurly/resources/coupon_discount_trial.rb +18 -0
  106. data/lib/recurly/resources/coupon_mini.rb +42 -0
  107. data/lib/recurly/resources/coupon_redemption.rb +50 -0
  108. data/lib/recurly/resources/coupon_redemption_mini.rb +34 -0
  109. data/lib/recurly/resources/credit_payment.rb +66 -0
  110. data/lib/recurly/resources/custom_field.rb +18 -0
  111. data/lib/recurly/resources/custom_field_definition.rb +50 -0
  112. data/lib/recurly/resources/error.rb +22 -0
  113. data/lib/recurly/resources/error_may_have_transaction.rb +26 -0
  114. data/lib/recurly/resources/export_dates.rb +18 -0
  115. data/lib/recurly/resources/export_file.rb +22 -0
  116. data/lib/recurly/resources/export_files.rb +18 -0
  117. data/lib/recurly/resources/fraud_info.rb +22 -0
  118. data/lib/recurly/resources/invoice.rb +146 -0
  119. data/lib/recurly/resources/invoice_address.rb +54 -0
  120. data/lib/recurly/resources/invoice_collection.rb +22 -0
  121. data/lib/recurly/resources/invoice_mini.rb +30 -0
  122. data/lib/recurly/resources/item.rb +82 -0
  123. data/lib/recurly/resources/item_mini.rb +34 -0
  124. data/lib/recurly/resources/line_item.rb +198 -0
  125. data/lib/recurly/resources/line_item_list.rb +26 -0
  126. data/lib/recurly/resources/measured_unit.rb +46 -0
  127. data/lib/recurly/resources/payment_method.rb +66 -0
  128. data/lib/recurly/resources/plan.rb +118 -0
  129. data/lib/recurly/resources/plan_hosted_pages.rb +26 -0
  130. data/lib/recurly/resources/plan_mini.rb +26 -0
  131. data/lib/recurly/resources/plan_pricing.rb +22 -0
  132. data/lib/recurly/resources/pricing.rb +18 -0
  133. data/lib/recurly/resources/settings.rb +22 -0
  134. data/lib/recurly/resources/shipping_address.rb +82 -0
  135. data/lib/recurly/resources/shipping_method.rb +46 -0
  136. data/lib/recurly/resources/shipping_method_mini.rb +26 -0
  137. data/lib/recurly/resources/site.rb +54 -0
  138. data/lib/recurly/resources/subscription.rb +174 -0
  139. data/lib/recurly/resources/subscription_add_on.rb +66 -0
  140. data/lib/recurly/resources/subscription_add_on_tier.rb +18 -0
  141. data/lib/recurly/resources/subscription_change.rb +78 -0
  142. data/lib/recurly/resources/subscription_change_preview.rb +78 -0
  143. data/lib/recurly/resources/subscription_shipping.rb +26 -0
  144. data/lib/recurly/resources/tax_info.rb +22 -0
  145. data/lib/recurly/resources/tier.rb +18 -0
  146. data/lib/recurly/resources/transaction.rb +158 -0
  147. data/lib/recurly/resources/transaction_error.rb +38 -0
  148. data/lib/recurly/resources/transaction_payment_gateway.rb +26 -0
  149. data/lib/recurly/resources/unique_coupon_code.rb +50 -0
  150. data/lib/recurly/resources/usage.rb +70 -0
  151. data/lib/recurly/resources/user.rb +42 -0
  152. data/lib/recurly/resources.rb +18 -0
  153. data/lib/recurly/schema/file_parser.rb +13 -0
  154. data/lib/recurly/schema/json_parser.rb +72 -0
  155. data/lib/recurly/schema/request_caster.rb +60 -0
  156. data/lib/recurly/schema/resource_caster.rb +46 -0
  157. data/lib/recurly/schema/schema_factory.rb +48 -0
  158. data/lib/recurly/schema/schema_validator.rb +144 -0
  159. data/lib/recurly/schema.rb +156 -0
  160. data/lib/recurly/version.rb +1 -15
  161. data/lib/recurly.rb +15 -137
  162. data/openapi/api.yaml +21024 -0
  163. data/recurly.gemspec +39 -0
  164. data/scripts/build +5 -0
  165. data/scripts/bump +11 -0
  166. data/scripts/changelog +14 -0
  167. data/scripts/clean +6 -0
  168. data/scripts/format +12 -0
  169. data/scripts/prepare-release +36 -0
  170. data/scripts/release +32 -0
  171. data/scripts/test +15 -0
  172. metadata +206 -168
  173. data/lib/recurly/account.rb +0 -169
  174. data/lib/recurly/account_balance.rb +0 -21
  175. data/lib/recurly/add_on.rb +0 -30
  176. data/lib/recurly/address.rb +0 -25
  177. data/lib/recurly/adjustment.rb +0 -76
  178. data/lib/recurly/api/errors.rb +0 -206
  179. data/lib/recurly/api/net_http_adapter.rb +0 -111
  180. data/lib/recurly/api.rb +0 -101
  181. data/lib/recurly/billing_info.rb +0 -80
  182. data/lib/recurly/coupon.rb +0 -134
  183. data/lib/recurly/credit_payment.rb +0 -28
  184. data/lib/recurly/custom_field.rb +0 -15
  185. data/lib/recurly/delivery.rb +0 -19
  186. data/lib/recurly/error.rb +0 -13
  187. data/lib/recurly/gift_card.rb +0 -79
  188. data/lib/recurly/helper.rb +0 -51
  189. data/lib/recurly/invoice.rb +0 -268
  190. data/lib/recurly/invoice_collection.rb +0 -14
  191. data/lib/recurly/js.rb +0 -14
  192. data/lib/recurly/juris_detail.rb +0 -14
  193. data/lib/recurly/measured_unit.rb +0 -16
  194. data/lib/recurly/money.rb +0 -120
  195. data/lib/recurly/plan.rb +0 -40
  196. data/lib/recurly/purchase.rb +0 -219
  197. data/lib/recurly/redemption.rb +0 -46
  198. data/lib/recurly/resource/association.rb +0 -16
  199. data/lib/recurly/resource/errors.rb +0 -20
  200. data/lib/recurly/resource/pager.rb +0 -314
  201. data/lib/recurly/shipping_address.rb +0 -22
  202. data/lib/recurly/subscription/add_ons.rb +0 -77
  203. data/lib/recurly/subscription.rb +0 -325
  204. data/lib/recurly/subscription_add_on.rb +0 -50
  205. data/lib/recurly/tax_detail.rb +0 -14
  206. data/lib/recurly/tax_type.rb +0 -12
  207. data/lib/recurly/transaction/errors.rb +0 -107
  208. data/lib/recurly/transaction.rb +0 -116
  209. data/lib/recurly/usage.rb +0 -24
  210. data/lib/recurly/webhook/account_notification.rb +0 -10
  211. data/lib/recurly/webhook/billing_info_updated_notification.rb +0 -6
  212. data/lib/recurly/webhook/canceled_account_notification.rb +0 -6
  213. data/lib/recurly/webhook/canceled_subscription_notification.rb +0 -6
  214. data/lib/recurly/webhook/closed_credit_invoice_notification.rb +0 -6
  215. data/lib/recurly/webhook/closed_invoice_notification.rb +0 -6
  216. data/lib/recurly/webhook/credit_payment_notification.rb +0 -12
  217. data/lib/recurly/webhook/dunning_notification.rb +0 -14
  218. data/lib/recurly/webhook/expired_subscription_notification.rb +0 -6
  219. data/lib/recurly/webhook/failed_charge_invoice_notification.rb +0 -6
  220. data/lib/recurly/webhook/failed_payment_notification.rb +0 -6
  221. data/lib/recurly/webhook/gift_card_notification.rb +0 -8
  222. data/lib/recurly/webhook/invoice_notification.rb +0 -12
  223. data/lib/recurly/webhook/new_account_notification.rb +0 -6
  224. data/lib/recurly/webhook/new_charge_invoice_notification.rb +0 -6
  225. data/lib/recurly/webhook/new_credit_invoice_notification.rb +0 -6
  226. data/lib/recurly/webhook/new_credit_payment_notification.rb +0 -6
  227. data/lib/recurly/webhook/new_dunning_event_notification.rb +0 -6
  228. data/lib/recurly/webhook/new_invoice_notification.rb +0 -6
  229. data/lib/recurly/webhook/new_subscription_notification.rb +0 -6
  230. data/lib/recurly/webhook/new_usage_notification.rb +0 -8
  231. data/lib/recurly/webhook/notification.rb +0 -18
  232. data/lib/recurly/webhook/paid_charge_invoice_notification.rb +0 -6
  233. data/lib/recurly/webhook/past_due_charge_invoice_notification.rb +0 -6
  234. data/lib/recurly/webhook/past_due_invoice_notification.rb +0 -6
  235. data/lib/recurly/webhook/processing_charge_invoice_notification.rb +0 -6
  236. data/lib/recurly/webhook/processing_credit_invoice_notification.rb +0 -6
  237. data/lib/recurly/webhook/processing_invoice_notification.rb +0 -6
  238. data/lib/recurly/webhook/processing_payment_notification.rb +0 -6
  239. data/lib/recurly/webhook/purchased_gift_card_notification.rb +0 -7
  240. data/lib/recurly/webhook/reactivated_account_notification.rb +0 -6
  241. data/lib/recurly/webhook/redeemed_gift_card_notification.rb +0 -7
  242. data/lib/recurly/webhook/renewed_subscription_notification.rb +0 -6
  243. data/lib/recurly/webhook/reopened_charge_invoice_notification.rb +0 -6
  244. data/lib/recurly/webhook/reopened_credit_invoice_notification.rb +0 -6
  245. data/lib/recurly/webhook/scheduled_payment_notification.rb +0 -6
  246. data/lib/recurly/webhook/subscription_notification.rb +0 -12
  247. data/lib/recurly/webhook/successful_payment_notification.rb +0 -6
  248. data/lib/recurly/webhook/successful_refund_notification.rb +0 -6
  249. data/lib/recurly/webhook/transaction_authorized_notification.rb +0 -6
  250. data/lib/recurly/webhook/transaction_notification.rb +0 -12
  251. data/lib/recurly/webhook/updated_account_notification.rb +0 -6
  252. data/lib/recurly/webhook/updated_balance_gift_card_notification.rb +0 -7
  253. data/lib/recurly/webhook/updated_subscription_notification.rb +0 -6
  254. data/lib/recurly/webhook/void_payment_notification.rb +0 -6
  255. data/lib/recurly/webhook/voided_credit_invoice_notification.rb +0 -6
  256. data/lib/recurly/webhook/voided_credit_payment_notification.rb +0 -6
  257. data/lib/recurly/webhook.rb +0 -88
  258. data/lib/recurly/xml/nokogiri.rb +0 -58
  259. data/lib/recurly/xml/rexml.rb +0 -50
  260. data/lib/recurly/xml.rb +0 -120
@@ -0,0 +1,26 @@
1
+ # This file is automatically created by Recurly's OpenAPI generation process
2
+ # and thus any edits you make by hand will be lost. If you wish to make a
3
+ # change to this file, please create a Github issue explaining the changes you
4
+ # need and we will usher them to the appropriate places.
5
+ module Recurly
6
+ module Resources
7
+ class TransactionPaymentGateway < Resource
8
+
9
+ # @!attribute id
10
+ # @return [String]
11
+ define_attribute :id, String
12
+
13
+ # @!attribute name
14
+ # @return [String]
15
+ define_attribute :name, String
16
+
17
+ # @!attribute object
18
+ # @return [String] Object type
19
+ define_attribute :object, String
20
+
21
+ # @!attribute type
22
+ # @return [String]
23
+ define_attribute :type, String
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,50 @@
1
+ # This file is automatically created by Recurly's OpenAPI generation process
2
+ # and thus any edits you make by hand will be lost. If you wish to make a
3
+ # change to this file, please create a Github issue explaining the changes you
4
+ # need and we will usher them to the appropriate places.
5
+ module Recurly
6
+ module Resources
7
+ class UniqueCouponCode < Resource
8
+
9
+ # @!attribute bulk_coupon_code
10
+ # @return [String] The Coupon code of the parent Bulk Coupon
11
+ define_attribute :bulk_coupon_code, String
12
+
13
+ # @!attribute bulk_coupon_id
14
+ # @return [String] The Coupon ID of the parent Bulk Coupon
15
+ define_attribute :bulk_coupon_id, String
16
+
17
+ # @!attribute code
18
+ # @return [String] The code the customer enters to redeem the coupon.
19
+ define_attribute :code, String
20
+
21
+ # @!attribute created_at
22
+ # @return [DateTime] Created at
23
+ define_attribute :created_at, DateTime
24
+
25
+ # @!attribute expired_at
26
+ # @return [DateTime] The date and time the coupon was expired early or reached its `max_redemptions`.
27
+ define_attribute :expired_at, DateTime
28
+
29
+ # @!attribute id
30
+ # @return [String] Unique Coupon Code ID
31
+ define_attribute :id, String
32
+
33
+ # @!attribute object
34
+ # @return [String] Object type
35
+ define_attribute :object, String
36
+
37
+ # @!attribute redeemed_at
38
+ # @return [DateTime] The date and time the unique coupon code was redeemed.
39
+ define_attribute :redeemed_at, DateTime
40
+
41
+ # @!attribute state
42
+ # @return [String] Indicates if the unique coupon code is redeemable or why not.
43
+ define_attribute :state, String
44
+
45
+ # @!attribute updated_at
46
+ # @return [DateTime] Updated at
47
+ define_attribute :updated_at, DateTime
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,70 @@
1
+ # This file is automatically created by Recurly's OpenAPI generation process
2
+ # and thus any edits you make by hand will be lost. If you wish to make a
3
+ # change to this file, please create a Github issue explaining the changes you
4
+ # need and we will usher them to the appropriate places.
5
+ module Recurly
6
+ module Resources
7
+ class Usage < Resource
8
+
9
+ # @!attribute amount
10
+ # @return [Float] The amount of usage. Can be positive, negative, or 0. No decimals allowed, we will strip them. If the usage-based add-on is billed with a percentage, your usage will be a monetary amount you will want to format in cents. (e.g., $5.00 is "500").
11
+ define_attribute :amount, Float
12
+
13
+ # @!attribute billed_at
14
+ # @return [DateTime] When the usage record was billed on an invoice.
15
+ define_attribute :billed_at, DateTime
16
+
17
+ # @!attribute created_at
18
+ # @return [DateTime] When the usage record was created in Recurly.
19
+ define_attribute :created_at, DateTime
20
+
21
+ # @!attribute id
22
+ # @return [String]
23
+ define_attribute :id, String
24
+
25
+ # @!attribute measured_unit_id
26
+ # @return [String] The ID of the measured unit associated with the add-on the usage record is for.
27
+ define_attribute :measured_unit_id, String
28
+
29
+ # @!attribute merchant_tag
30
+ # @return [String] Custom field for recording the id in your own system associated with the usage, so you can provide auditable usage displays to your customers using a GET on this endpoint.
31
+ define_attribute :merchant_tag, String
32
+
33
+ # @!attribute object
34
+ # @return [String] Object type
35
+ define_attribute :object, String
36
+
37
+ # @!attribute recording_timestamp
38
+ # @return [DateTime] When the usage was recorded in your system.
39
+ define_attribute :recording_timestamp, DateTime
40
+
41
+ # @!attribute tier_type
42
+ # @return [String] The pricing model for the add-on. For more information, [click here](https://docs.recurly.com/docs/billing-models#section-quantity-based).
43
+ define_attribute :tier_type, String
44
+
45
+ # @!attribute tiers
46
+ # @return [Array[SubscriptionAddOnTier]] The tiers and prices of the subscription based on the usage_timestamp. If tier_type = flat, tiers = null
47
+ define_attribute :tiers, Array, { :item_type => :SubscriptionAddOnTier }
48
+
49
+ # @!attribute unit_amount
50
+ # @return [Float] Unit price
51
+ define_attribute :unit_amount, Float
52
+
53
+ # @!attribute updated_at
54
+ # @return [DateTime] When the usage record was billed on an invoice.
55
+ define_attribute :updated_at, DateTime
56
+
57
+ # @!attribute usage_percentage
58
+ # @return [Float] The percentage taken of the monetary amount of usage tracked. This can be up to 4 decimal places. A value between 0.0 and 100.0.
59
+ define_attribute :usage_percentage, Float
60
+
61
+ # @!attribute usage_timestamp
62
+ # @return [DateTime] When the usage actually happened. This will define the line item dates this usage is billed under and is important for revenue recognition.
63
+ define_attribute :usage_timestamp, DateTime
64
+
65
+ # @!attribute usage_type
66
+ # @return [String] Type of usage, returns usage type if `add_on_type` is `usage`.
67
+ define_attribute :usage_type, String
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,42 @@
1
+ # This file is automatically created by Recurly's OpenAPI generation process
2
+ # and thus any edits you make by hand will be lost. If you wish to make a
3
+ # change to this file, please create a Github issue explaining the changes you
4
+ # need and we will usher them to the appropriate places.
5
+ module Recurly
6
+ module Resources
7
+ class User < Resource
8
+
9
+ # @!attribute created_at
10
+ # @return [DateTime]
11
+ define_attribute :created_at, DateTime
12
+
13
+ # @!attribute deleted_at
14
+ # @return [DateTime]
15
+ define_attribute :deleted_at, DateTime
16
+
17
+ # @!attribute email
18
+ # @return [String]
19
+ define_attribute :email, String
20
+
21
+ # @!attribute first_name
22
+ # @return [String]
23
+ define_attribute :first_name, String
24
+
25
+ # @!attribute id
26
+ # @return [String]
27
+ define_attribute :id, String
28
+
29
+ # @!attribute last_name
30
+ # @return [String]
31
+ define_attribute :last_name, String
32
+
33
+ # @!attribute object
34
+ # @return [String] Object type
35
+ define_attribute :object, String
36
+
37
+ # @!attribute time_zone
38
+ # @return [String]
39
+ define_attribute :time_zone, String
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,18 @@
1
+ # Include all resource files
2
+ resources = File.join(File.dirname(__FILE__), "resources", "*.rb")
3
+ Dir.glob(resources, &method(:require))
4
+
5
+ module Recurly
6
+ module Resources
7
+ class Empty < Resource
8
+ end
9
+
10
+ class Page < Resource
11
+ # leave data untyped
12
+ define_attribute :data, Array, item_type: Hash
13
+ define_attribute :has_more, :Boolean
14
+ define_attribute :next, String
15
+ define_attribute :object, String
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,13 @@
1
+ module Recurly
2
+ # This is a wrapper class to help parse http response into Recurly objects.
3
+ class FileParser
4
+
5
+ # Parses the json body into a recurly object.
6
+ #
7
+ # @param body [String] The data string to cast.
8
+ # @return [Resource]
9
+ def self.parse(body)
10
+ Recurly::Resources::BinaryFile.cast(data: body)
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,72 @@
1
+ require "json"
2
+
3
+ module Recurly
4
+ # This is a wrapper class to help parse http response into Recurly objects.
5
+ class JSONParser
6
+
7
+ # Parses the json body into a recurly object.
8
+ #
9
+ # @param client [Client] The Recurly client which made the request.
10
+ # @param body [String] The JSON string to parse.
11
+ # @return [Resource]
12
+ def self.parse(client, body)
13
+ data = JSON.parse(body)
14
+ from_json(data).tap do |object|
15
+ object.client = client if object.requires_client?
16
+ end
17
+ end
18
+
19
+ # Converts the parsed JSON into a Recurly object.
20
+ #
21
+ # *TODO*: Instead of inferring this type from the `object`
22
+ # attribute. We should instead "register" the response type
23
+ # in the client/operations code. The `get`, `post`, etc methods
24
+ # could explicitly state their response types.
25
+ #
26
+ # @param data [Hash] The parsed JSON data
27
+ # @return [Error,Resource]
28
+ def self.from_json(data)
29
+ type = if data.has_key?("error")
30
+ "error_may_have_transaction"
31
+ else
32
+ data["object"]
33
+ end
34
+ klazz = self.recurly_class(type)
35
+
36
+ unless klazz
37
+ raise ArgumentError, "Unknown resource for json type #{type}"
38
+ end
39
+
40
+ data = data["error"] if klazz == Resources::ErrorMayHaveTransaction
41
+
42
+ klazz.cast(data)
43
+ end
44
+
45
+ # Returns the Recurly ruby class responsible for the Recurly json key.
46
+ #
47
+ # @example
48
+ # JSONParser.recurly_class('list')
49
+ # #=> Recurly::Page
50
+ # @example
51
+ # JSONParser.recurly_class('shipping_address')
52
+ # #=> Recurly::Resources::ShippingAddress
53
+ #
54
+ # @param type [String] The JSON key.
55
+ # @return [Resource,Pager,nil]
56
+ def self.recurly_class(type)
57
+ case type
58
+ when nil
59
+ nil
60
+ when "list"
61
+ Resources::Page
62
+ else
63
+ type_camelized = type.split("_").map(&:capitalize).join
64
+ if Resources.const_defined?(type_camelized, false)
65
+ Resources.const_get(type_camelized, false)
66
+ elsif Recurly::STRICT_MODE
67
+ raise ArgumentError, "Could not find Recurly Resource responsible for key #{type}"
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,60 @@
1
+ require "date"
2
+
3
+ module Recurly
4
+ class Schema
5
+ # *Note*: This module is for internal use.
6
+ # The RequestCaster turns mixed data into a pure Hash
7
+ # so it can be serialized into JSON and used as the body of a request.
8
+ # This module is to be extended by the Request class.
9
+ module RequestCaster
10
+
11
+ # This method casts the data object (of mixed types) into a Hash ready for JSON
12
+ # serialization. The *schema* will default to the self's schema.
13
+ # You should pass in the schema where possible. This is because objects are serialized
14
+ # differently depending on the context in which they are being written.
15
+ #
16
+ # @example
17
+ # Recurly::Requests::AccountUpdatable.cast(code: 'benjamin')
18
+ # #=> {:code=>"benjamin"}
19
+ # @example
20
+ # # If you have some mixed data, like passing in an Address, it should cast that
21
+ # # address into a Hash based on the Schema defined in AccountUpdatable
22
+ # address = Recurly::Resources::Address.new(city: 'New Orleans')
23
+ # Recurly::Requests::AccountUpdatable.cast(account_code: 'benjamin', address: address)
24
+ # #=> {:account_code=>"benjamin", :address=>{:city=>"New Orleans"}}
25
+ #
26
+ # @param data [Hash,Resource,Request] The data to transform into a JSON Hash.
27
+ # @param schema [Schema] The schema to use to transform the data into a JSON Hash.
28
+ # @return [Hash] The pure Hash ready to be serialized into JSON.
29
+ def cast_request(data, schema = self.schema)
30
+ casted = {}
31
+ if data.is_a?(Resource) || data.is_a?(Request)
32
+ data = data.attributes.reject { |_k, v| v.nil? }
33
+ end
34
+
35
+ data.each do |k, v|
36
+ schema_attr = schema.get_attribute(k)
37
+ norm_val = if v.respond_to?(:attributes)
38
+ cast_request(v, v.class.schema)
39
+ elsif v.is_a?(Array)
40
+ v.map do |elem|
41
+ if elem.respond_to?(:attributes)
42
+ cast_request(elem, elem.class.schema)
43
+ else
44
+ elem
45
+ end
46
+ end
47
+ elsif v.is_a?(Hash) && schema_attr && schema_attr.is_a?(Schema::ResourceAttribute)
48
+ cast_request(v, schema_attr.recurly_class.schema)
49
+ else
50
+ v
51
+ end
52
+
53
+ casted[k] = norm_val
54
+ end
55
+
56
+ casted
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,46 @@
1
+ require "date"
2
+
3
+ module Recurly
4
+ class Schema
5
+ # The purpose of this class is to turn JSON parsed Hashes
6
+ # defined into Recurly ruby objects. It's to be used
7
+ # by the Resource as an extension.
8
+ module ResourceCaster
9
+
10
+ # Gives the class the ability to initialize itself
11
+ # given some json data.
12
+ #
13
+ # @example
14
+ # Recurly::Resources::Account.cast({"code" => "mycode"})
15
+ # #=> #<Recurly::Resources::Account @attributes={:code=>"mycode"}>
16
+ #
17
+ # @param attributes [Hash] A primitive Hash from JSON.parse of Recurly response.
18
+ # @return [Resource] the {Resource} (ruby object) representing the passed in JSON data.
19
+ def cast(attributes = {})
20
+ resource = new()
21
+ attributes.each do |attr_name, val|
22
+ schema_attr = self.schema.get_attribute(attr_name)
23
+
24
+ if schema_attr
25
+ val = if val.nil?
26
+ val
27
+ elsif schema_attr.is_valid?(val)
28
+ schema_attr.cast(val)
29
+ else
30
+ if Recurly::STRICT_MODE
31
+ msg = "#{self.class}##{attr_name} does not have the right type. Value: #{val.inspect} was expected to be a #{schema_attr}"
32
+ raise ArgumentError, msg
33
+ end
34
+ end
35
+
36
+ writer = "#{attr_name}="
37
+ resource.send(writer, val)
38
+ elsif Recurly::STRICT_MODE
39
+ raise ArgumentError, "#{resource.class.name} encountered json attribute #{attr_name.inspect}: #{val.inspect} but it's unknown to it's schema"
40
+ end
41
+ end
42
+ resource
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,48 @@
1
+ module Recurly
2
+ class Schema
3
+ # A mixin that allows a class to be treated like a recurly
4
+ # object. This gives the class the power to describe
5
+ # it's schema. It adds the *define_attribute* method
6
+ # and a *schema* reader.
7
+ module SchemaFactory
8
+
9
+ # Gets the schema for this class
10
+ # @return [Schema]
11
+ def schema
12
+ @schema ||= ::Recurly::Schema.new
13
+ end
14
+
15
+ protected
16
+
17
+ # Macro that allows this class to define it's schema and associated
18
+ # attribute getters and setters.
19
+ #
20
+ # @example
21
+ # class Account
22
+ # extend Schema::SchemaFactory
23
+ # define_attribute :code, String, {:read_only=>true}
24
+ # end
25
+ # account = Account.new(code: "mycode")
26
+ # account.schema
27
+ # #=> Recurly::Schema
28
+ # acount.code = "newcode" # this method protected since read_only = true
29
+ # account.code
30
+ # #=> "mycode"
31
+ def define_attribute(name, type, options = {})
32
+ attribute = schema.add_attribute(name, type, options)
33
+
34
+ # Define the reader
35
+ define_method(name) do
36
+ self.attributes[name]
37
+ end
38
+
39
+ # Define the writer
40
+ define_method("#{name}=") do |val|
41
+ self.attributes[name] = val
42
+ end
43
+
44
+ self
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,144 @@
1
+ module Recurly
2
+ class Schema
3
+ # This module is responsible for validating that the raw data
4
+ # passed in to *attributes* matches the schema belonging to this class.
5
+ # It should be mixed in to the Request class.
6
+ module SchemaValidator
7
+ # Validates the attributes and throws an error if something is wrong.
8
+ #
9
+ # @example
10
+ # Recurly::Requests::PlanCreate.new(code: 'plan123').validate!
11
+ # #=> {:code=>"plan123"}
12
+ # @example
13
+ # Recurly::Requests::PlanCreate.new(code: 3.14).validate!
14
+ # #=> ArgumentError: Attribute 'code' on the resource Recurly::Requests::PlanCreate is type Float but should be a String.
15
+ # @example
16
+ # Recurly::Requests::PlanCreate.new(kode: 'plan123').validate!
17
+ # #=> ArgumentError: Attribute 'kode' does not exist on request Recurly::Requests::PlanCreate. Did you mean 'code'?
18
+ #
19
+ # @raise [ArgumentError] if the attribute data does not match the schema.
20
+ def validate!
21
+ attributes.each do |attr_name, val|
22
+ schema_attr = schema.get_attribute(attr_name)
23
+ if schema_attr.nil?
24
+ err_msg = "Attribute '#{attr_name}' does not exist on request #{self.class.name}."
25
+ if did_you_mean = get_did_you_mean(schema, attr_name)
26
+ err_msg << " Did you mean '#{did_you_mean}'?"
27
+ end
28
+ raise ArgumentError, err_msg
29
+ else
30
+ validate_attribute!(attr_name, schema_attr, val)
31
+ end
32
+ end
33
+ end
34
+
35
+ # Validates an individual attribute
36
+ def validate_attribute!(name, schema_attr, val)
37
+ unless val.nil? || schema_attr.is_valid?(val)
38
+ # If it's safely castable, the json deserializer or server
39
+ # will take care of it for us
40
+ unless safely_castable?(val.class, schema_attr.type)
41
+ expected = case schema_attr
42
+ when Schema::ArrayAttribute
43
+ "Array of #{schema_attr.type}s"
44
+ else
45
+ schema_attr.type
46
+ end
47
+
48
+ raise ArgumentError, "Attribute '#{name}' on the resource #{self.class.name} is type #{val.class} but should be a #{expected}"
49
+ end
50
+ end
51
+
52
+ # This is the convention for a recurly object
53
+ if schema_attr.is_a?(Schema::ResourceAttribute) && val.is_a?(Hash)
54
+ # Using send because the initializer may be private
55
+ instance = schema_attr.recurly_class.send(:new, val)
56
+ instance.validate!
57
+ end
58
+ end
59
+
60
+ # Gets the closest term to the misspelled attribute
61
+ def get_did_you_mean(schema, misspelled_attr)
62
+ closest = schema.attributes.keys.sort_by do |v|
63
+ levenshtein_distance(v, misspelled_attr)
64
+ end.first
65
+
66
+ if closest && levenshtein_distance(closest, misspelled_attr) <= 4
67
+ closest
68
+ end
69
+ end
70
+
71
+ private
72
+
73
+ def safely_castable?(from_type, to_type)
74
+ # TODO we can drop this switch when 2.3 support is dropped
75
+ int_class = if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("2.4.0")
76
+ :Integer
77
+ else
78
+ :Fixnum
79
+ end
80
+ int_class = Kernel.const_get(int_class)
81
+
82
+ case [from_type, to_type]
83
+ when [Symbol, String]
84
+ true
85
+ when [int_class, Float]
86
+ true
87
+ else
88
+ false
89
+ end
90
+ end
91
+
92
+ # This code is copied directly from the did_you mean gem which is based
93
+ # directly on the Text gem implementation.
94
+ #
95
+ # did_you_mean: Copyright (c) 2014-2016 Yuki Nishijima.
96
+ # Text: Copyright (c) 2006-2013 Paul Battley, Michael Neumann, Tim Fletcher.
97
+ #
98
+ # Returns a value representing the "cost" of transforming str1 into str2
99
+ def levenshtein_distance(str1, str2)
100
+ str1 = str1.to_s unless str1.is_a? String
101
+ str2 = str2.to_s unless str2.is_a? String
102
+ n = str1.length
103
+ m = str2.length
104
+ return m if n.zero?
105
+ return n if m.zero?
106
+
107
+ d = (0..m).to_a
108
+ x = nil
109
+
110
+ # to avoid duplicating an enumerable object, create it outside of the loop
111
+ str2_codepoints = str2.codepoints
112
+
113
+ str1.each_codepoint.with_index(1) do |char1, i|
114
+ j = 0
115
+ while j < m
116
+ cost = (char1 == str2_codepoints[j]) ? 0 : 1
117
+ x = min3(
118
+ d[j + 1] + 1, # insertion
119
+ i + 1, # deletion
120
+ d[j] + cost # substitution
121
+ )
122
+ d[j] = i
123
+ i = x
124
+
125
+ j += 1
126
+ end
127
+ d[m] = x
128
+ end
129
+
130
+ x
131
+ end
132
+
133
+ def min3(a, b, c)
134
+ if a < b && a < c
135
+ a
136
+ elsif b < c
137
+ b
138
+ else
139
+ c
140
+ end
141
+ end
142
+ end
143
+ end
144
+ end