paypal-sdk-core 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +11 -0
- data/README.md +16 -0
- data/Rakefile +5 -0
- data/lib/generators/paypal/sdk/USAGE +3 -0
- data/lib/generators/paypal/sdk/install_generator.rb +17 -0
- data/lib/generators/paypal/sdk/templates/paypal.rb +2 -0
- data/lib/generators/paypal/sdk/templates/paypal.yml +32 -0
- data/lib/paypal-sdk-core.rb +40 -0
- data/lib/paypal-sdk/core/api/base.rb +166 -0
- data/lib/paypal-sdk/core/api/data_types/base.rb +236 -0
- data/lib/paypal-sdk/core/api/data_types/enum.rb +26 -0
- data/lib/paypal-sdk/core/api/data_types/simple_types.rb +47 -0
- data/lib/paypal-sdk/core/api/merchant.rb +122 -0
- data/lib/paypal-sdk/core/api/platform.rb +75 -0
- data/lib/paypal-sdk/core/authentication.rb +79 -0
- data/lib/paypal-sdk/core/config.rb +138 -0
- data/lib/paypal-sdk/core/credential/base.rb +27 -0
- data/lib/paypal-sdk/core/credential/certificate.rb +32 -0
- data/lib/paypal-sdk/core/credential/signature.rb +22 -0
- data/lib/paypal-sdk/core/credential/third_party/subject.rb +25 -0
- data/lib/paypal-sdk/core/credential/third_party/token.rb +39 -0
- data/lib/paypal-sdk/core/logging.rb +43 -0
- data/lib/paypal-sdk/core/util/oauth_signature.rb +64 -0
- data/lib/paypal-sdk/core/version.rb +7 -0
- data/spec/config/cert_key.pem +33 -0
- data/spec/config/paypal.yml +29 -0
- data/spec/core/api/data_type_spec.rb +164 -0
- data/spec/core/api/merchant_spec.rb +114 -0
- data/spec/core/api/platform_spec.rb +107 -0
- data/spec/core/config_spec.rb +48 -0
- data/spec/core/logging_spec.rb +28 -0
- data/spec/log/test.log +84 -0
- data/spec/spec_helper.rb +11 -0
- metadata +109 -0
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
# Paypal::Sdk::Core
|
2
|
+
|
3
|
+
Core library for PayPal ruby SDKs.
|
4
|
+
|
5
|
+
SDKs:
|
6
|
+
|
7
|
+
* [paypal-sdk-adaptivepayments](https://github.com/paypal/adaptivepayments-sdk-ruby)
|
8
|
+
* [paypal-sdk-adaptiveaccounts](https://github.com/paypal/adaptiveaccounts-sdk-ruby)
|
9
|
+
* [paypal-sdk-invoice](https://github.com/paypal/invoice-sdk-ruby)
|
10
|
+
* [paypal-sdk-permissions](https://github.com/paypal/permissions-sdk-ruby)
|
11
|
+
* [paypal-sdk-merchant](https://github.com/paypal/merchant-sdk-ruby)
|
12
|
+
* [paypal-sdk-buttonmanager](https://github.com/paypal/buttonmanager-sdk-ruby)
|
13
|
+
|
14
|
+
|
15
|
+
Note: Don't use this library directly
|
16
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
module Paypal
|
2
|
+
module Sdk
|
3
|
+
module Generators
|
4
|
+
class InstallGenerator < Rails::Generators::Base
|
5
|
+
source_root File.expand_path('../templates', __FILE__)
|
6
|
+
|
7
|
+
def copy_config_file
|
8
|
+
copy_file "paypal.yml", "config/paypal.yml"
|
9
|
+
end
|
10
|
+
|
11
|
+
def copy_initializer_file
|
12
|
+
copy_file "paypal.rb", "config/initializers/paypal.rb"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
test: &default
|
2
|
+
username: jb-us-seller_api1.paypal.com
|
3
|
+
password: WX4WTU3S8MY44S7F
|
4
|
+
signature: AFcWxV21C7fd0v3bYYYRCpSSRl31A7yDhhsPUU2XhtMoZXsWHFxu-RWy
|
5
|
+
app_id: APP-80W284485P519543T
|
6
|
+
http_timeout: 30
|
7
|
+
mode: sandbox
|
8
|
+
sandbox_email_address: Platform.sdk.seller@gmail.com
|
9
|
+
|
10
|
+
development:
|
11
|
+
<<: *default
|
12
|
+
|
13
|
+
production:
|
14
|
+
<<: *default
|
15
|
+
mode: live
|
16
|
+
|
17
|
+
# with_certificate:
|
18
|
+
# <<: *default
|
19
|
+
# username: platfo_1255170694_biz_api1.gmail.com
|
20
|
+
# password: 2DPPKUPKB7DQLXNR
|
21
|
+
# signature:
|
22
|
+
# cert_path: "config/cert_key.pem"
|
23
|
+
# app_id: APP-80W284485P519543T
|
24
|
+
#
|
25
|
+
# with_oauth_token:
|
26
|
+
# <<: *default
|
27
|
+
# token: ESTy2hio5WJQo1iixkH29I53RJxaS0Gvno1A6.YQXZgktxbY4I2Tdg
|
28
|
+
# token_secret: ZKPhUYuwJwYsfWdzorozWO2U9pI
|
29
|
+
#
|
30
|
+
# with_proxy:
|
31
|
+
# <<: *default
|
32
|
+
# http_proxy: http://proxy-ipaddress:3129/
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require "paypal-sdk/core/version"
|
2
|
+
require "paypal-sdk/core/config"
|
3
|
+
require "paypal-sdk/core/logging"
|
4
|
+
|
5
|
+
module PayPal
|
6
|
+
module SDK
|
7
|
+
module Core
|
8
|
+
|
9
|
+
autoload :Authentication, "paypal-sdk/core/authentication"
|
10
|
+
|
11
|
+
module API
|
12
|
+
autoload :Base, "paypal-sdk/core/api/base"
|
13
|
+
autoload :Merchant, "paypal-sdk/core/api/merchant"
|
14
|
+
autoload :Platform, "paypal-sdk/core/api/platform"
|
15
|
+
|
16
|
+
module DataTypes
|
17
|
+
autoload :Base, "paypal-sdk/core/api/data_types/base"
|
18
|
+
autoload :Enum, "paypal-sdk/core/api/data_types/enum"
|
19
|
+
autoload :SimpleTypes, "paypal-sdk/core/api/data_types/simple_types"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
module Util
|
24
|
+
autoload :OauthSignature, "paypal-sdk/core/util/oauth_signature"
|
25
|
+
end
|
26
|
+
|
27
|
+
module Credential
|
28
|
+
autoload :Base, "paypal-sdk/core/credential/base"
|
29
|
+
autoload :Certificate, "paypal-sdk/core/credential/certificate"
|
30
|
+
autoload :Signature, "paypal-sdk/core/credential/signature"
|
31
|
+
|
32
|
+
module ThirdParty
|
33
|
+
autoload :Token, "paypal-sdk/core/credential/third_party/token"
|
34
|
+
autoload :Subject, "paypal-sdk/core/credential/third_party/subject"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,166 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
|
3
|
+
module PayPal::SDK::Core
|
4
|
+
|
5
|
+
module API
|
6
|
+
# API class provide default functionality for accessing the API web services.
|
7
|
+
# == Example
|
8
|
+
# api = API::Base.new("AdaptivePayments")
|
9
|
+
# response = api.request("GetPaymentOptions", "")
|
10
|
+
class Base
|
11
|
+
|
12
|
+
include Configuration
|
13
|
+
include Logging
|
14
|
+
include Authentication
|
15
|
+
|
16
|
+
attr_accessor :http, :uri, :service_name
|
17
|
+
|
18
|
+
DEFAULT_END_POINTS = {
|
19
|
+
:sandbox => {
|
20
|
+
:platform => { # NVP EndPoint
|
21
|
+
:three_token => "https://svcs.sandbox.paypal.com/",
|
22
|
+
:certificate => "https://svcs.sandbox.paypal.com/"
|
23
|
+
},
|
24
|
+
:merchant => { # SOAP EndPoint
|
25
|
+
:three_token => "https://api-3t.sandbox.paypal.com/2.0",
|
26
|
+
:certificate => "https://api.sandbox.paypal.com/2.0"
|
27
|
+
}
|
28
|
+
},
|
29
|
+
:live => {
|
30
|
+
:platform => { # NVP EndPoint
|
31
|
+
:three_token => "https://svcs.paypal.com/",
|
32
|
+
:certificate => "https://svcs.paypal.com/"
|
33
|
+
},
|
34
|
+
:merchant => { # SOAP EndPoint
|
35
|
+
:three_token => "https://api-3t.paypal.com/2.0",
|
36
|
+
:certificate => "https://api.paypal.com/2.0"
|
37
|
+
}
|
38
|
+
}
|
39
|
+
}
|
40
|
+
DEFAULT_HTTP_HEADER = {}
|
41
|
+
|
42
|
+
# Initialize API object
|
43
|
+
# === Argument
|
44
|
+
# * <tt>service_name</tt> -- (Optional) Service name
|
45
|
+
# * <tt>environment</tt> -- (Optional) Configuration environment to load
|
46
|
+
# * <tt>options</tt> -- (Optional) Override configuration.
|
47
|
+
# === Example
|
48
|
+
# new("AdaptivePayments")
|
49
|
+
# new("AdaptivePayments", :development)
|
50
|
+
# new(:wsdl_service) # It load wsdl_service configuration
|
51
|
+
def initialize(service_name = "", environment = nil, options = {})
|
52
|
+
unless service_name.is_a? String
|
53
|
+
environment, options, service_name = service_name, environment || {}, ""
|
54
|
+
end
|
55
|
+
@service_name = service_name
|
56
|
+
set_config(environment, options)
|
57
|
+
end
|
58
|
+
|
59
|
+
# Override set_config method to create http connection on changing the configuration.
|
60
|
+
def set_config(*args)
|
61
|
+
super
|
62
|
+
create_http_connection
|
63
|
+
end
|
64
|
+
|
65
|
+
# Create HTTP connection based on given service name or configured end point
|
66
|
+
def create_http_connection
|
67
|
+
service_path = "#{service_endpoint}/#{service_name}"
|
68
|
+
@uri = URI.parse(service_path)
|
69
|
+
if config.http_proxy
|
70
|
+
proxy = URI.parse(config.http_proxy)
|
71
|
+
@http = Net::HTTP.new(@uri.host, @uri.port, proxy.host, proxy.port, proxy.user, proxy.password)
|
72
|
+
else
|
73
|
+
@http = Net::HTTP.new(@uri.host, @uri.port)
|
74
|
+
end
|
75
|
+
@uri.path = @uri.path.gsub(/\/+/, "/")
|
76
|
+
configure_http_connection
|
77
|
+
end
|
78
|
+
|
79
|
+
# Configure HTTP connection based on configuration.
|
80
|
+
def configure_http_connection
|
81
|
+
http.use_ssl = true
|
82
|
+
http.ca_file = config.ca_file if config.ca_file
|
83
|
+
if config.http_timeout
|
84
|
+
http.open_timeout = config.http_timeout
|
85
|
+
http.read_timeout = config.http_timeout
|
86
|
+
end
|
87
|
+
add_certificate(http)
|
88
|
+
end
|
89
|
+
|
90
|
+
# Get configured API mode( sandbox or live)
|
91
|
+
def api_mode
|
92
|
+
api_modes = DEFAULT_END_POINTS.keys
|
93
|
+
config_mode = ( config.mode || api_modes.first ).to_sym
|
94
|
+
api_modes.include?(config_mode) ? config_mode : api_modes.first
|
95
|
+
end
|
96
|
+
|
97
|
+
# Get default endpoint for the given service name
|
98
|
+
# === Argument
|
99
|
+
# * <tt>name</tt> -- Service name ( platform or merchant)
|
100
|
+
# === Returns
|
101
|
+
# Return service end point based on the configured API mode.
|
102
|
+
def default_end_point(name)
|
103
|
+
default_end_point = DEFAULT_END_POINTS[api_mode][name]
|
104
|
+
if default_end_point
|
105
|
+
config.cert_path ? default_end_point[:certificate] : default_end_point[:three_token]
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
# Get service end point
|
110
|
+
def service_endpoint
|
111
|
+
config.end_point ? default_end_point(config.end_point.to_sym) : config.end_point
|
112
|
+
end
|
113
|
+
|
114
|
+
# Default Http header
|
115
|
+
def default_http_header
|
116
|
+
DEFAULT_HTTP_HEADER
|
117
|
+
end
|
118
|
+
|
119
|
+
# Generate HTTP request for given action and parameters
|
120
|
+
# === Arguments
|
121
|
+
# * <tt>action</tt> -- Action to perform
|
122
|
+
# * <tt>params</tt> -- (Optional) Parameters for the action
|
123
|
+
# * <tt>initheader</tt> -- (Optional) HTTP header
|
124
|
+
def request(action, params = {}, initheader = {})
|
125
|
+
uri, content, header = format_request(action, params)
|
126
|
+
initheader = default_http_header.merge(header).merge(initheader)
|
127
|
+
initheader.delete_if{|key, val| val.nil? }
|
128
|
+
start_time = Time.now
|
129
|
+
response = @http.post(uri.path, content, initheader)
|
130
|
+
format_response(action, response)
|
131
|
+
rescue Net::HTTPBadGateway, Errno::ECONNRESET, Errno::ECONNABORTED, SocketError => error
|
132
|
+
format_error(error, error.message)
|
133
|
+
ensure
|
134
|
+
log_event("Request: #{action}", start_time)
|
135
|
+
end
|
136
|
+
|
137
|
+
# Format Request data. It will be override by child class
|
138
|
+
# == Arguments
|
139
|
+
# * <tt>action</tt> -- Request action
|
140
|
+
# * <tt>params</tt> -- Request parameters
|
141
|
+
# == Return
|
142
|
+
# * <tt>path</tt> -- Formated request uri object
|
143
|
+
# * <tt>params</tt> -- Formated request Parameters
|
144
|
+
# * <tt>header</tt> -- HTTP Header
|
145
|
+
def format_request(action, params)
|
146
|
+
[ @uri, params, {} ]
|
147
|
+
end
|
148
|
+
|
149
|
+
# Format Response object. It will be override by child class
|
150
|
+
# == Argument
|
151
|
+
# * <tt>action</tt> -- Request action
|
152
|
+
# * <tt>response</tt> -- HTTP response object
|
153
|
+
def format_response(action, response)
|
154
|
+
response
|
155
|
+
end
|
156
|
+
|
157
|
+
# Format Error object. It will be override by child class.
|
158
|
+
# == Arguments
|
159
|
+
# * <tt>exception</tt> -- Exception object.
|
160
|
+
# * <tt>message</tt> -- Readable error message.
|
161
|
+
def format_error(exception, message)
|
162
|
+
raise exception
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
@@ -0,0 +1,236 @@
|
|
1
|
+
require 'date'
|
2
|
+
|
3
|
+
module PayPal::SDK::Core
|
4
|
+
module API
|
5
|
+
|
6
|
+
module DataTypes
|
7
|
+
|
8
|
+
# Create attributes and restrict the object type.
|
9
|
+
# == Example
|
10
|
+
# class ConvertCurrencyRequest < Core::API::DataTypes::Base
|
11
|
+
# object_of :baseAmountList, CurrencyList
|
12
|
+
# object_of :convertToCurrencyList, CurrencyCodeList
|
13
|
+
# object_of :countryCode, String
|
14
|
+
# object_of :conversionType, String
|
15
|
+
# end
|
16
|
+
class Base
|
17
|
+
|
18
|
+
HashOptions = { :attribute => true, :namespace => true, :symbol => true }
|
19
|
+
ContentKey = :value
|
20
|
+
|
21
|
+
include SimpleTypes
|
22
|
+
|
23
|
+
class << self
|
24
|
+
|
25
|
+
# Add attribute
|
26
|
+
# === Arguments
|
27
|
+
# * <tt>name</tt> -- attribute name
|
28
|
+
# * <tt>options</tt> -- options
|
29
|
+
def add_attribute(name, options = {})
|
30
|
+
add_member(name, SimpleTypes::String, options.merge( :attribute => true ))
|
31
|
+
end
|
32
|
+
|
33
|
+
# Fields list for the DataTye
|
34
|
+
def members
|
35
|
+
@members ||=
|
36
|
+
begin
|
37
|
+
parent_members = superclass.instance_variable_get("@members")
|
38
|
+
parent_members ? parent_members.dup : {}
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# Add Field to class variable hash and generate methods
|
43
|
+
# === Example
|
44
|
+
# add_member(:errorMessage, String) # Generate Code
|
45
|
+
# # attr_reader :errorMessage
|
46
|
+
# # alias_method :error_message, :errorMessage
|
47
|
+
# # alias_method :error_message=, :errorMessage=
|
48
|
+
def add_member(member_name, klass, options = {})
|
49
|
+
member_name = member_name.to_sym
|
50
|
+
members[member_name] = options.merge( :type => klass )
|
51
|
+
member_variable_name = "@#{member_name}"
|
52
|
+
define_method "#{member_name}=" do |value|
|
53
|
+
object = options[:array] ? convert_array(value, klass) : convert_object(value, klass)
|
54
|
+
instance_variable_set(member_variable_name, object)
|
55
|
+
end
|
56
|
+
default_value = ( options[:array] ? [] : ( klass < Base ? {} : nil ) )
|
57
|
+
define_method member_name do |&block|
|
58
|
+
value = instance_variable_get(member_variable_name) || ( default_value && send("#{member_name}=", default_value) )
|
59
|
+
value.instance_eval(&block) if block
|
60
|
+
value
|
61
|
+
end
|
62
|
+
define_alias_methods(member_name, options)
|
63
|
+
end
|
64
|
+
|
65
|
+
# Define alias methods for getter and setter
|
66
|
+
def define_alias_methods(member_name, options)
|
67
|
+
snakecase_name = snakecase(member_name)
|
68
|
+
alias_method snakecase_name, member_name
|
69
|
+
alias_method "#{snakecase_name}=", "#{member_name}="
|
70
|
+
alias_method "#{options[:namespace]}:#{member_name}=", "#{member_name}=" if options[:namespace]
|
71
|
+
if options[:attribute]
|
72
|
+
alias_method "@#{member_name}=", "#{member_name}="
|
73
|
+
alias_method "@#{options[:namespace]}:#{member_name}=", "#{member_name}=" if options[:namespace]
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
# define method for given member and the class name
|
78
|
+
# === Example
|
79
|
+
# object_of(:errorMessage, ErrorMessage) # Generate Code
|
80
|
+
# # def errorMessage=(options)
|
81
|
+
# # @errorMessage = ErrorMessage.new(options)
|
82
|
+
# # end
|
83
|
+
# # add_member :errorMessage, ErrorMessage
|
84
|
+
def object_of(key, klass, options = {})
|
85
|
+
add_member(key, klass, options)
|
86
|
+
end
|
87
|
+
|
88
|
+
# define method for given member and the class name
|
89
|
+
# === Example
|
90
|
+
# array_of(:errorMessage, ErrorMessage) # It Generate below code
|
91
|
+
# # def errorMessage=(array)
|
92
|
+
# # @errorMessage = array.map{|options| ErrorMessage.new(options) }
|
93
|
+
# # end
|
94
|
+
# # add_member :errorMessage, ErrorMessage
|
95
|
+
def array_of(key, klass, options = {})
|
96
|
+
add_member(key, klass, options.merge(:array => true))
|
97
|
+
end
|
98
|
+
|
99
|
+
# Generate snakecase string.
|
100
|
+
# === Example
|
101
|
+
# snakecase("errorMessage")
|
102
|
+
# # error_message
|
103
|
+
def snakecase(string)
|
104
|
+
string.to_s.gsub(/([a-z])([A-Z])/, '\1_\2').gsub(/([A-Z])([A-Z][a-z])/, '\1_\2').downcase
|
105
|
+
end
|
106
|
+
|
107
|
+
end
|
108
|
+
|
109
|
+
# Initialize options.
|
110
|
+
def initialize(options = {}, &block)
|
111
|
+
if options.is_a? Hash
|
112
|
+
options.each do |key, value|
|
113
|
+
begin
|
114
|
+
send("#{key}=", value)
|
115
|
+
rescue TypeError, ArgumentError => error
|
116
|
+
raise TypeError, "#{error.message}(#{value.inspect}) for #{self.class.name}.#{key} member"
|
117
|
+
end
|
118
|
+
end
|
119
|
+
elsif members[ContentKey]
|
120
|
+
self.value = options
|
121
|
+
else
|
122
|
+
raise ArgumentError, "invalid data(#{options.inspect}) for #{self.class.name} class"
|
123
|
+
end
|
124
|
+
self.instance_eval(&block) if block
|
125
|
+
end
|
126
|
+
|
127
|
+
# Create Array with default value.
|
128
|
+
class ArrayWithDefault < ::Array
|
129
|
+
def initialize(&block)
|
130
|
+
@block = block
|
131
|
+
super()
|
132
|
+
end
|
133
|
+
|
134
|
+
def [](key)
|
135
|
+
super(key) || send(:"[]=", key, nil)
|
136
|
+
end
|
137
|
+
|
138
|
+
def []=(key, value)
|
139
|
+
super(key, @block ? @block.call(value) : value )
|
140
|
+
end
|
141
|
+
|
142
|
+
def merge!(array)
|
143
|
+
if array.is_a? Array
|
144
|
+
array.each_with_index do |object, index|
|
145
|
+
self[index] = object
|
146
|
+
end
|
147
|
+
elsif array.is_a? Hash and array.keys.first.to_s =~ /^\d+$/
|
148
|
+
array.each do |key, object|
|
149
|
+
self[key.to_i] = object
|
150
|
+
end
|
151
|
+
else
|
152
|
+
self[0] = array
|
153
|
+
end
|
154
|
+
self
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
# Create array of objects.
|
159
|
+
# === Example
|
160
|
+
# covert_array([{ :amount => "55", :code => "USD"}], CurrencyType)
|
161
|
+
# covert_array({ "0" => { :amount => "55", :code => "USD"} }, CurrencyType)
|
162
|
+
# covert_array({ :amount => "55", :code => "USD"}, CurrencyType)
|
163
|
+
# # @return
|
164
|
+
# # [ <CurrencyType#object @amount="55" @code="USD" > ]
|
165
|
+
def convert_array(array, klass)
|
166
|
+
default_value = ( klass < Base ? {} : nil )
|
167
|
+
data_type_array = ArrayWithDefault.new{|object| convert_object(object || default_value, klass) }
|
168
|
+
data_type_array.merge!(array)
|
169
|
+
end
|
170
|
+
|
171
|
+
# Create object based on given data.
|
172
|
+
# === Example
|
173
|
+
# covert_object({ :amount => "55", :code => "USD"}, CurrencyType )
|
174
|
+
# # @return
|
175
|
+
# # <CurrencyType#object @amount="55" @code="USD" >
|
176
|
+
def convert_object(object, klass)
|
177
|
+
object.is_a?(klass) ? object : ( ( object.nil? or object == "" ) ? nil : klass.new(object) )
|
178
|
+
end
|
179
|
+
|
180
|
+
# Alias instance method for the class method.
|
181
|
+
def members
|
182
|
+
self.class.members
|
183
|
+
end
|
184
|
+
|
185
|
+
# Get configured member names
|
186
|
+
def member_names
|
187
|
+
members.keys
|
188
|
+
end
|
189
|
+
|
190
|
+
# Create Hash based configured members
|
191
|
+
def to_hash(options = {})
|
192
|
+
options = HashOptions.merge(options)
|
193
|
+
hash = {}
|
194
|
+
member_names.each do |member|
|
195
|
+
value = value_to_hash(instance_variable_get("@#{member}"), options)
|
196
|
+
hash[hash_key(member, options)] = value unless skip_value?(value)
|
197
|
+
end
|
198
|
+
hash
|
199
|
+
end
|
200
|
+
|
201
|
+
# Skip nil, empty array and empty hash.
|
202
|
+
def skip_value?(value)
|
203
|
+
value.nil? || ( ( value.is_a?(Array) || value.is_a?(Hash) ) && value.empty? )
|
204
|
+
end
|
205
|
+
|
206
|
+
# Generate Hash key for given member name based on configuration
|
207
|
+
# === Example
|
208
|
+
# hash_key(:amount) # @return :"ebl:amount"
|
209
|
+
# hash_key(:type) # @return :"@type"
|
210
|
+
def hash_key(key, options = {})
|
211
|
+
unless key == ContentKey
|
212
|
+
member_option = members[key]
|
213
|
+
key = member_option[:name] if member_option.include? :name
|
214
|
+
key = "#{member_option[:namespace]}:#{key}" if member_option[:namespace] and options[:namespace]
|
215
|
+
key = "@#{key}" if member_option[:attribute] and options[:attribute]
|
216
|
+
end
|
217
|
+
options[:symbol] ? key.to_sym : key.to_s
|
218
|
+
end
|
219
|
+
|
220
|
+
# Covert the object to hash based on class.
|
221
|
+
def value_to_hash(value, options = {})
|
222
|
+
case value
|
223
|
+
when Array
|
224
|
+
value = value.map{|object| value_to_hash(object, options) }
|
225
|
+
value.delete_if{|v| skip_value?(v) }
|
226
|
+
value
|
227
|
+
when Base
|
228
|
+
value.to_hash(options)
|
229
|
+
else
|
230
|
+
value
|
231
|
+
end
|
232
|
+
end
|
233
|
+
end
|
234
|
+
end
|
235
|
+
end
|
236
|
+
end
|