transbank-sdk 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +14 -0
- data/.travis.yml +8 -0
- data/CHANGELOG.md +13 -0
- data/Dockerfile +6 -0
- data/Gemfile +6 -0
- data/LICENSE.md +11 -0
- data/Makefile +24 -0
- data/README.md +87 -0
- data/Rakefile +10 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/docker-compose.yml +20 -0
- data/lib/transbank/sdk.rb +23 -0
- data/lib/transbank/sdk/onepay/base.rb +115 -0
- data/lib/transbank/sdk/onepay/errors/errors.rb +17 -0
- data/lib/transbank/sdk/onepay/errors/integration_type_error.rb +8 -0
- data/lib/transbank/sdk/onepay/errors/invalid_options_error.rb +8 -0
- data/lib/transbank/sdk/onepay/errors/item_error.rb +8 -0
- data/lib/transbank/sdk/onepay/errors/refund_create_error.rb +8 -0
- data/lib/transbank/sdk/onepay/errors/response_error.rb +8 -0
- data/lib/transbank/sdk/onepay/errors/shopping_cart_error.rb +8 -0
- data/lib/transbank/sdk/onepay/errors/signature_error.rb +8 -0
- data/lib/transbank/sdk/onepay/errors/transaction_commit_error.rb +8 -0
- data/lib/transbank/sdk/onepay/errors/transaction_create_error.rb +8 -0
- data/lib/transbank/sdk/onepay/errors/transbank_error.rb +9 -0
- data/lib/transbank/sdk/onepay/models/channels.rb +15 -0
- data/lib/transbank/sdk/onepay/models/item.rb +103 -0
- data/lib/transbank/sdk/onepay/models/models.rb +10 -0
- data/lib/transbank/sdk/onepay/models/refund.rb +51 -0
- data/lib/transbank/sdk/onepay/models/shopping_cart.rb +65 -0
- data/lib/transbank/sdk/onepay/models/transaction.rb +141 -0
- data/lib/transbank/sdk/onepay/requests/refund_create_request.rb +45 -0
- data/lib/transbank/sdk/onepay/requests/request.rb +18 -0
- data/lib/transbank/sdk/onepay/requests/requests.rb +9 -0
- data/lib/transbank/sdk/onepay/requests/transaction_commit_request.rb +48 -0
- data/lib/transbank/sdk/onepay/requests/transaction_create_request.rb +80 -0
- data/lib/transbank/sdk/onepay/responses/refund_create_response.rb +24 -0
- data/lib/transbank/sdk/onepay/responses/response.rb +18 -0
- data/lib/transbank/sdk/onepay/responses/responses.rb +9 -0
- data/lib/transbank/sdk/onepay/responses/transaction_commit_response.rb +39 -0
- data/lib/transbank/sdk/onepay/responses/transaction_create_response.rb +32 -0
- data/lib/transbank/sdk/onepay/utils/json_utils.rb +73 -0
- data/lib/transbank/sdk/onepay/utils/net_helper.rb +38 -0
- data/lib/transbank/sdk/onepay/utils/request_builder.rb +88 -0
- data/lib/transbank/sdk/onepay/utils/signature_utils.rb +49 -0
- data/lib/transbank/sdk/onepay/utils/utils.rb +9 -0
- data/lib/transbank/sdk/version.rb +5 -0
- data/sdk_test.sh +2 -0
- data/transbank-sdk.gemspec +33 -0
- metadata +220 -0
@@ -0,0 +1,45 @@
|
|
1
|
+
module Transbank
|
2
|
+
module Onepay
|
3
|
+
# Creates a Refund request
|
4
|
+
class RefundCreateRequest
|
5
|
+
include Request
|
6
|
+
attr_accessor :nullify_amount, :occ, :external_unique_number,
|
7
|
+
:authorization_code, :issued_at, :signature
|
8
|
+
|
9
|
+
# These are the params used to build this class's @signature
|
10
|
+
SIGNATURE_PARAMS = [:occ,
|
11
|
+
:external_unique_number,
|
12
|
+
:authorization_code,
|
13
|
+
:issued_at,
|
14
|
+
:nullify_amount].freeze
|
15
|
+
|
16
|
+
# @param nullify_amount [Integer, nil] The total amount of the [Transaction] to Refund.
|
17
|
+
# No partial refunds are possible
|
18
|
+
# @param external_unique_number [String] a unique value (per Merchant, not global) that is used to identify a Transaction
|
19
|
+
# @param occ [String] Merchant purchase order
|
20
|
+
# @param authorization_code [String] a string returned when [Transaction]#commit completes correctly
|
21
|
+
# @param issued_at [Integer, nil] a timestamp
|
22
|
+
# @param signature [String, nil] a hashed string to verify the data
|
23
|
+
def initialize(nullify_amount: nil,
|
24
|
+
occ: nil,
|
25
|
+
external_unique_number: nil,
|
26
|
+
authorization_code: nil,
|
27
|
+
issued_at: nil,
|
28
|
+
signature: nil)
|
29
|
+
@nullify_amount = nullify_amount
|
30
|
+
@occ = occ
|
31
|
+
@external_unique_number = external_unique_number
|
32
|
+
@authorization_code = authorization_code
|
33
|
+
@issued_at = issued_at
|
34
|
+
@signature = signature
|
35
|
+
end
|
36
|
+
|
37
|
+
# Create and set the signature for this instance of RefundCreateRequest
|
38
|
+
# @return [RefundCreateRequest] returns self
|
39
|
+
def sign(secret)
|
40
|
+
@signature = signature_for(to_data, secret)
|
41
|
+
self
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Transbank
|
2
|
+
module Onepay
|
3
|
+
# Base module with methods & attributes common to Requests
|
4
|
+
module Request
|
5
|
+
include Utils::JSONUtils, Utils::SignatureUtils
|
6
|
+
attr_accessor :api_key
|
7
|
+
attr_accessor :app_key
|
8
|
+
|
9
|
+
# Set the request's @api_key overriding the one in
|
10
|
+
# the [Base] class
|
11
|
+
def set_keys_from_options(options)
|
12
|
+
transform_hash_keys(options)
|
13
|
+
new_api_key = options.fetch(:api_key, nil)
|
14
|
+
self.api_key = new_api_key unless new_api_key.nil?
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
require 'transbank/sdk/onepay/requests/request'
|
2
|
+
require 'transbank/sdk/onepay/requests/transaction_create_request'
|
3
|
+
require 'transbank/sdk/onepay/requests/transaction_commit_request'
|
4
|
+
require 'transbank/sdk/onepay/requests/refund_create_request'
|
5
|
+
|
6
|
+
module Transbank
|
7
|
+
module Onepay
|
8
|
+
end
|
9
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module Transbank
|
2
|
+
module Onepay
|
3
|
+
# Creates a request to Transbank attempting to commit a [Transaction]
|
4
|
+
class TransactionCommitRequest
|
5
|
+
include Request
|
6
|
+
attr_reader :occ, :external_unique_number, :issued_at, :signature
|
7
|
+
|
8
|
+
SIGNATURE_PARAMS = [:occ,
|
9
|
+
:external_unique_number,
|
10
|
+
:issued_at].freeze
|
11
|
+
# @param occ [String] Merchant purchase order
|
12
|
+
# @param external_unique_number [String] a unique value (per Merchant, not global) that is used to identify a Transaction
|
13
|
+
# @param issued_at [Integer] timestamp for when the transaction commit request was created
|
14
|
+
def initialize(occ, external_unique_number, issued_at)
|
15
|
+
self.occ = occ
|
16
|
+
self.external_unique_number = external_unique_number
|
17
|
+
self.issued_at = issued_at
|
18
|
+
@signature = nil
|
19
|
+
end
|
20
|
+
|
21
|
+
# @param occ [String] Merchant purchase order
|
22
|
+
def occ=(occ)
|
23
|
+
raise Errors::TransactionCommitError, 'occ cannot be null.' if occ.nil?
|
24
|
+
@occ = occ
|
25
|
+
end
|
26
|
+
|
27
|
+
# @param external_unique_number [String] a unique value (per Merchant, not global) that is used to identify a Transaction
|
28
|
+
def external_unique_number=(external_unique_number)
|
29
|
+
raise Errors::TransactionCommitError, 'external_unique_number cannot be null.' if external_unique_number.nil?
|
30
|
+
@external_unique_number = external_unique_number
|
31
|
+
end
|
32
|
+
|
33
|
+
# @param issued_at [Integer] timestamp for when the transaction commit request was created
|
34
|
+
def issued_at=(issued_at)
|
35
|
+
raise Errors::TransactionCommitError, 'issued_at cannot be null.' if issued_at.nil?
|
36
|
+
@issued_at = issued_at
|
37
|
+
end
|
38
|
+
|
39
|
+
# Create a signature string and assign it to @signature
|
40
|
+
# @return [TransactionCommitRequest] self
|
41
|
+
def sign(secret)
|
42
|
+
@signature = signature_for(to_data, secret)
|
43
|
+
self
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
module Transbank
|
2
|
+
module Onepay
|
3
|
+
# Create a payload to create [Transaction] on Transbank
|
4
|
+
class TransactionCreateRequest
|
5
|
+
include Request
|
6
|
+
|
7
|
+
attr_accessor :external_unique_number, :total, :items_quantity, :issued_at,
|
8
|
+
:items, :callback_url, :channel, :app_scheme, :signature
|
9
|
+
attr_reader :generate_ott_qr_code
|
10
|
+
|
11
|
+
SIGNATURE_PARAMS = [:external_unique_number,
|
12
|
+
:total,
|
13
|
+
:items_quantity,
|
14
|
+
:issued_at,
|
15
|
+
:callback_url].freeze
|
16
|
+
# @param opts [Hash] options hash with params needed to initialize this
|
17
|
+
# @param external_unique_number [String] Unique identifier (per Merchant) of the [Transaction] that
|
18
|
+
# @param total [Numeric] the total amount to pay for the items
|
19
|
+
# @param items_quantity [Numeric] the quantity of items on the shopping cart
|
20
|
+
# @param items [Array<Item] the items on the shopping cart
|
21
|
+
# @param issued_at [Numeric] timestamp at the moment the transaction is created
|
22
|
+
# @param callback_url [String] used when the channel is mobile, to be able to finish the [Transaction]
|
23
|
+
# @param channel [String] The channel the operation is made on. Valid values
|
24
|
+
# are on the [Channel] class
|
25
|
+
# @param app_scheme [String] identificator for the Merchant's app
|
26
|
+
# @param signature [String, nil] a hashstring created for verification purposes
|
27
|
+
def initialize(opts = {})
|
28
|
+
self.external_unique_number = opts.fetch(:external_unique_number)
|
29
|
+
self.total = opts.fetch(:total)
|
30
|
+
self.items_quantity = opts.fetch(:items_quantity)
|
31
|
+
self.items = opts.fetch(:items)
|
32
|
+
self.issued_at = opts.fetch(:issued_at)
|
33
|
+
self.callback_url = opts.fetch(:callback_url)
|
34
|
+
channel = opts.fetch(:channel, Channel::WEB)
|
35
|
+
self.channel = channel
|
36
|
+
self.app_scheme = opts.fetch(:app_scheme, '')
|
37
|
+
self.signature = nil
|
38
|
+
# This is never anything but true, but it is required by the server
|
39
|
+
@generate_ott_qr_code = true
|
40
|
+
end
|
41
|
+
|
42
|
+
def external_unique_number=(external_unique_number)
|
43
|
+
raise Errors::TransactionCreateError, 'External Unique Number cannot be null.' if external_unique_number.nil?
|
44
|
+
@external_unique_number = external_unique_number
|
45
|
+
end
|
46
|
+
|
47
|
+
def total=(total)
|
48
|
+
raise Errors::TransactionCreateError, 'Total cannot be null.' if total.nil?
|
49
|
+
raise Errors::TransactionCreateError, 'Total cannot be less than zero.' if total < 0
|
50
|
+
@total = total
|
51
|
+
end
|
52
|
+
|
53
|
+
def items_quantity=(items_quantity)
|
54
|
+
raise Errors::TransactionCreateError, 'Items quantity cannot be null.' if items_quantity.nil?
|
55
|
+
raise Errors::TransactionCreateError, 'Items quantity cannot be less than zero.' if items_quantity < 0
|
56
|
+
@items_quantity = items_quantity
|
57
|
+
end
|
58
|
+
|
59
|
+
def items=(items)
|
60
|
+
raise Errors::TransactionCreateError, 'Items must not be empty.' if items.empty?
|
61
|
+
@items = items
|
62
|
+
end
|
63
|
+
|
64
|
+
def callback_url=(callback_url)
|
65
|
+
raise Errors::TransactionCreateError, 'Callback url cannot be null.' if callback_url.nil?
|
66
|
+
@callback_url = callback_url
|
67
|
+
end
|
68
|
+
|
69
|
+
def channel=(channel)
|
70
|
+
raise Errors::TransactionCreateError, 'Channel cannot be null.' if channel.nil?
|
71
|
+
channel
|
72
|
+
end
|
73
|
+
|
74
|
+
def sign(secret)
|
75
|
+
@signature = signature_for(to_data, secret)
|
76
|
+
self
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Transbank
|
2
|
+
module Onepay
|
3
|
+
# Serializes the response to a RefundCreateRequest
|
4
|
+
class RefundCreateResponse
|
5
|
+
include Response
|
6
|
+
attr_accessor :occ, :external_unique_number, :reverse_code, :issued_at,
|
7
|
+
:signature
|
8
|
+
# @raise []RefundCreateError] if the responseCode from the service is not 'OK'
|
9
|
+
def initialize(json)
|
10
|
+
unless json.fetch('responseCode').downcase == 'ok'
|
11
|
+
raise Errors::RefundCreateError, "#{json.fetch('responseCode')} : #{json.fetch('description')}"
|
12
|
+
end
|
13
|
+
result = json.fetch('result')
|
14
|
+
@response_code = json.fetch('responseCode')
|
15
|
+
@description = json.fetch('description')
|
16
|
+
@occ = result.fetch('occ')
|
17
|
+
@external_unique_number = result.fetch('externalUniqueNumber')
|
18
|
+
@reverse_code = result.fetch('reverseCode')
|
19
|
+
@issued_at = result.fetch('issuedAt')
|
20
|
+
@signature = result.fetch('signature')
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Transbank
|
2
|
+
module Onepay
|
3
|
+
# Shared methods and attributes between all types of Responses
|
4
|
+
module Response
|
5
|
+
include Utils::SignatureUtils, Utils::JSONUtils
|
6
|
+
attr_accessor :response_code
|
7
|
+
attr_accessor :description
|
8
|
+
|
9
|
+
def response_ok?
|
10
|
+
response_code.downcase == 'ok'
|
11
|
+
end
|
12
|
+
|
13
|
+
def full_description
|
14
|
+
"#{ response_code } : #{ description }"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
require 'transbank/sdk/onepay/responses/response'
|
2
|
+
require 'transbank/sdk/onepay/responses/refund_create_response'
|
3
|
+
require 'transbank/sdk/onepay/responses/transaction_commit_response'
|
4
|
+
require 'transbank/sdk/onepay/responses/transaction_create_response'
|
5
|
+
|
6
|
+
module Transbank
|
7
|
+
module Onepay
|
8
|
+
end
|
9
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Transbank
|
2
|
+
module Onepay
|
3
|
+
# Serializes the response to a TransactionCommitRequest
|
4
|
+
class TransactionCommitResponse
|
5
|
+
include Response
|
6
|
+
|
7
|
+
attr_accessor :occ, :authorization_code, :signature, :transaction_desc,
|
8
|
+
:buy_order, :issued_at, :amount, :installments_amount,
|
9
|
+
:installments_number
|
10
|
+
|
11
|
+
SIGNATURE_PARAMS = [:occ,
|
12
|
+
:authorization_code,
|
13
|
+
:issued_at,
|
14
|
+
:amount,
|
15
|
+
:installments_amount,
|
16
|
+
:installments_number,
|
17
|
+
:buy_order].freeze
|
18
|
+
# @raise [KeyError] upon missing a response parameter
|
19
|
+
def initialize(json)
|
20
|
+
result = json.fetch('result')
|
21
|
+
@response_code = json.fetch('responseCode')
|
22
|
+
@description = json.fetch('description')
|
23
|
+
@occ = result.fetch('occ')
|
24
|
+
@authorization_code = result.fetch('authorizationCode')
|
25
|
+
@signature = result.fetch('signature')
|
26
|
+
@transaction_desc = result.fetch('transactionDesc')
|
27
|
+
@buy_order = result.fetch('buyOrder')
|
28
|
+
@issued_at = result.fetch('issuedAt')
|
29
|
+
@amount = result.fetch('amount')
|
30
|
+
@installments_amount = result.fetch('installmentsAmount')
|
31
|
+
@installments_number = result.fetch('installmentsNumber')
|
32
|
+
end
|
33
|
+
|
34
|
+
def sign(secret)
|
35
|
+
@signature = signature_for(to_data, secret)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Transbank
|
2
|
+
module Onepay
|
3
|
+
# Serializes the response to a TransactionCreateRequest
|
4
|
+
class TransactionCreateResponse
|
5
|
+
include Response
|
6
|
+
|
7
|
+
attr_accessor :occ, :ott, :external_unique_number, :qr_code_as_base64,
|
8
|
+
:issued_at, :signature
|
9
|
+
|
10
|
+
SIGNATURE_PARAMS = [:occ,
|
11
|
+
:external_unique_number,
|
12
|
+
:issued_at].freeze
|
13
|
+
# @raise [KeyError] upon trying to fetch a missing key from the response
|
14
|
+
def initialize(json)
|
15
|
+
result = json.fetch('result')
|
16
|
+
@response_code = json.fetch('responseCode')
|
17
|
+
@description = json.fetch('description')
|
18
|
+
@occ = result.fetch('occ')
|
19
|
+
@ott = result.fetch('ott')
|
20
|
+
@external_unique_number = result.fetch('externalUniqueNumber')
|
21
|
+
@qr_code_as_base64 = result.fetch('qrCodeAsBase64')
|
22
|
+
@issued_at = result.fetch('issuedAt')
|
23
|
+
@signature = result.fetch('signature')
|
24
|
+
end
|
25
|
+
|
26
|
+
def sign(secret)
|
27
|
+
@signature = signature_for(to_data, secret)
|
28
|
+
self
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
module Transbank
|
2
|
+
module Onepay
|
3
|
+
module Utils
|
4
|
+
module JSONUtils
|
5
|
+
def self.included(mod)
|
6
|
+
# Implement #to_h if the class that includes this module doesn't have it
|
7
|
+
# implemented. Used in several model classes to make them easier to
|
8
|
+
# transform to hashes so they can be transformed to JSON afterwards
|
9
|
+
unless mod.respond_to? :to_h
|
10
|
+
mod.send(:define_method, :to_h) do
|
11
|
+
JSON.parse(self.jsonify)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
# Get all instance variables of an instance of a class,
|
16
|
+
# then for all of these variables,
|
17
|
+
# if the instance of the class' respond_to? returns true,
|
18
|
+
# #send the variable name (so, you'll get the value of the instance variable's
|
19
|
+
# getter), then save that to a Hash where [key] is the instance variable's name
|
20
|
+
# and [value] is its value
|
21
|
+
#
|
22
|
+
# Finally, generate a JSON string from this hash
|
23
|
+
# @return [String] a JSON string created from the Hash resulting from the
|
24
|
+
# above operation
|
25
|
+
def jsonify
|
26
|
+
instance_vars = instance_variables.map! { |var| var.to_s.gsub!(/^@/, '') }
|
27
|
+
instance_as_hash =
|
28
|
+
instance_vars.reduce({}) do |resulting_hash, instance_variable|
|
29
|
+
if respond_to? instance_variable
|
30
|
+
value = send(instance_variable)
|
31
|
+
# Safe navigation operator is Ruby 2.3+
|
32
|
+
value = value.to_h if value && value.respond_to?(:to_h) unless value.is_a? Array
|
33
|
+
value = value.to_a if value && value.respond_to?(:to_a) unless value.is_a? Hash
|
34
|
+
if value.is_a? Array
|
35
|
+
value = value.map {|x| x.respond_to?(:jsonify) ? JSON.parse(x.jsonify) : x }
|
36
|
+
end
|
37
|
+
|
38
|
+
value = value.jsonify if value.respond_to? :jsonify
|
39
|
+
resulting_hash[instance_variable] = value
|
40
|
+
end
|
41
|
+
resulting_hash
|
42
|
+
end
|
43
|
+
JSON.generate instance_as_hash
|
44
|
+
end
|
45
|
+
|
46
|
+
# Receive a Hash and return a new hash same as the one we received,
|
47
|
+
# but all keys that were strings or camelCase'd are snake_case'd and
|
48
|
+
# turned into symbols.
|
49
|
+
# Example: {'camelCaseKey': "somevalue"}
|
50
|
+
# Would return: {camel_case_key: "somevalue"}
|
51
|
+
def transform_hash_keys(hash)
|
52
|
+
hash.reduce({}) do |new_hsh, (key, val)|
|
53
|
+
new_key = underscore(key).to_sym
|
54
|
+
new_hsh[new_key] = val
|
55
|
+
new_hsh
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
# FROM https://stackoverflow.com/a/1509957
|
60
|
+
# Transforms camelCaseWords to snake_case_words
|
61
|
+
def underscore(camel_cased_word)
|
62
|
+
camel_cased_word.to_s.gsub(/::/, '/')
|
63
|
+
.gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2')
|
64
|
+
.gsub(/([a-z\d])([A-Z])/,'\1_\2')
|
65
|
+
.tr("-", "_")
|
66
|
+
.downcase
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Transbank
|
2
|
+
module Onepay
|
3
|
+
module Utils
|
4
|
+
module NetHelper
|
5
|
+
# POST a request to Transbank's servers, and return the parsed response
|
6
|
+
# @param uri_string [String] an URI to post to
|
7
|
+
# @param body [Hash] the body of your POST request
|
8
|
+
# @return [Hash] the JSON.parse'd response body
|
9
|
+
def http_post(uri_string, body)
|
10
|
+
uri = URI.parse(uri_string)
|
11
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
12
|
+
http.use_ssl = uri.scheme == 'https'
|
13
|
+
request = Net::HTTP::Post.new(uri.path, 'Content-Type'=> 'application/json')
|
14
|
+
camel_cased_body = keys_to_camel_case(body)
|
15
|
+
request.body = JSON.generate(camel_cased_body)
|
16
|
+
result = http.request(request)
|
17
|
+
JSON.parse(result.body)
|
18
|
+
end
|
19
|
+
|
20
|
+
# Required for sending data to Transbank.
|
21
|
+
def keys_to_camel_case(hash)
|
22
|
+
hash.reduce({}) do |new_hash, (key, val)|
|
23
|
+
if val.is_a? Array
|
24
|
+
val = val.map {|value| value.is_a?(Hash) ? keys_to_camel_case(value) : value }
|
25
|
+
end
|
26
|
+
new_key = snake_to_camel_case(key.to_s)
|
27
|
+
new_hash[new_key] = val
|
28
|
+
new_hash
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def snake_to_camel_case(str)
|
33
|
+
str.split('_').reduce { |string, current_word| string + current_word.capitalize }
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|