Class: EbayTrader::Request

Inherits:
Object
  • Object
show all
Defined in:
lib/ebay_trader/request.rb

Direct Known Subclasses

FetchToken, SessionID

Defined Under Namespace

Classes: Error

Constant Summary collapse

XMLNS =

eBay Trading API XML Namespace

'urn:ebay:apis:eBLBaseComponents'

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(call_name, args = {}) {|xml_builder| ... } ⇒ Request

Construct a new eBay Trading API call.

Parameters:

  • call_name (String)

    the name of the API call, for example ‘GeteBayOfficialTime’.

  • args (Hash) (defaults to: {})

    optional configuration values for this request.

Options Hash (args):

  • :auth_token (String)

    the eBay Auth Token for the user submitting this request. If not defined the value of Configuration#auth_token will be assumed.

  • :ebay_site_id (Fixnum)

    Override the default eBay site ID in Configuration#ebay_site_id

  • :http_timeout (Fixnum)

    Override the default value of Configuration#http_timeout.

    This may be necessary for one-off calls such as UploadSiteHostedPictures which can take significantly longer.

  • :skip_type_casting (Array [String])

    An array of the keys for which the values should not get automatically type cast.

    Take for example the ‘BuyerUserID’ field. If someone has the username ‘123456’ the auto-type-casting would consider this to be a Fixnum. Adding ‘BuyerUserID’ to skip_type_casting list will ensure it remains a String.

  • :known_arrays (Array [String])

    a list of the names of elements that are known to have arrays of values. If defined here #response_hash will ensure array values in circumstances where there is only a single child element in the response XML.

    It is not necessary to use this feature, but doing so can simplify later stage logic as certain fields are guaranteed to be arrays. As there is no concept of arrays in XML it is not otherwise possible to determine if a field should be an array.

    An example case is when building a tree of nested categories. Some categories may only have one child category, but adding ‘Category’ or :category to this list will ensure the response_hash values is always an array. Hence it will not necessary to check if the elements of a category element is a Hash or an Array of Hashes when recursing through the data.

  • :xml_response (String)

    inject a pre-prepared XML response.

    If an XML response is given here the request will not actually be sent to eBay. Using this feature can dramatically speed up testing and also ensure you stay within eBay’s 5,000 requests per day throttling rate.

    It is also a useful feature for parsing locally cached/archived XML files.

  • :xml_tab_width (Fixnum)

    the number of spaces to indent child elements in the generated XML. The default is 0, meaning the XML is a single line string, but it’s nice to have the option of pretty-printing the XML for debugging.

Yields:

  • (xml_builder)

    a block describing the XML DOM.

Yield Parameters:

  • name (XMLBuilder)

    an XML builder node allowing customization of the request specific details.

Yield Returns:

  • (XMLBuilder)

    the same XML builder originally provided by the block.

Raises:



100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
# File 'lib/ebay_trader/request.rb', line 100

def initialize(call_name, args = {}, &block)
  time = Time.now
  @call_name  = call_name.freeze

  auth_token = %w"GetSessionID FetchToken GetTokenStatus RevokeToken".include?(call_name) ?
                  nil : (args[:auth_token] || EbayTrader.configuration.auth_token)
  @auth_token = auth_token.freeze

  @ebay_site_id = (args[:ebay_site_id] || EbayTrader.configuration.ebay_site_id).to_i
  @http_timeout = (args[:http_timeout] || EbayTrader.configuration.http_timeout).to_f
  @xml_tab_width = (args[:xml_tab_width] || 0).to_i

  @xml_response = args[:xml_response] || ''

  @skip_type_casting = args[:skip_type_casting] || []
  @skip_type_casting = @skip_type_casting.split if @skip_type_casting.is_a?(String)

  @known_arrays = args[:known_arrays] || []
  @known_arrays = @known_arrays.split if @known_arrays.is_a?(String)
  @known_arrays << 'errors'

  @message_id = nil
  if args.key?(:message_id)
    @message_id = (args[:message_id] == true) ? SecureRandom.uuid : args[:message_id].to_s
  end

  @xml_request = '<?xml version="1.0" encoding="utf-8"?>' << "\n"
  @xml_request << XMLBuilder.new(tab_width: xml_tab_width).root("#{call_name}Request", xmlns: XMLNS) do
    unless auth_token.blank?
      RequesterCredentials do
        eBayAuthToken auth_token.to_s
      end
    end
    instance_eval(&block) if block_given?
    MessageID message_id unless message_id.nil?
  end

  @http_response_code = 200
  submit if xml_response.blank?

  parsed_hash = parse(xml_response)
  root_key = parsed_hash.keys.first
  raise EbayTraderError, "Response '#{root_key}' does not match call name" unless root_key.gsub('_', '').eql?("#{call_name}Response".downcase)

  @response_hash = parsed_hash[root_key]
  @response_hash.freeze
  @response_time = Time.now - time

  @errors = []
  deep_find(:errors, []).each do |error|
    @errors << Error.new(error[:error_classification],
                         error[:severity_code],
                         error[:error_code],
                         error[:short_message],
                         error[:long_message])
  end
end

Instance Attribute Details

#auth_tokenObject (readonly)

Returns the value of attribute auth_token.



28
29
30
# File 'lib/ebay_trader/request.rb', line 28

def auth_token
  @auth_token
end

#call_nameObject (readonly)

Returns the value of attribute call_name.



27
28
29
# File 'lib/ebay_trader/request.rb', line 27

def call_name
  @call_name
end

#ebay_site_idObject (readonly)

Returns the value of attribute ebay_site_id.



29
30
31
# File 'lib/ebay_trader/request.rb', line 29

def ebay_site_id
  @ebay_site_id
end

#http_response_codeObject (readonly)

Returns the value of attribute http_response_code.



38
39
40
# File 'lib/ebay_trader/request.rb', line 38

def http_response_code
  @http_response_code
end

#http_timeoutObject (readonly)

Returns the value of attribute http_timeout.



37
38
39
# File 'lib/ebay_trader/request.rb', line 37

def http_timeout
  @http_timeout
end

#known_arraysObject (readonly)

Returns the value of attribute known_arrays.



33
34
35
# File 'lib/ebay_trader/request.rb', line 33

def known_arrays
  @known_arrays
end

#message_idObject (readonly)

Returns the value of attribute message_id.



30
31
32
# File 'lib/ebay_trader/request.rb', line 30

def message_id
  @message_id
end

#response_hashObject (readonly)

Returns the value of attribute response_hash.



31
32
33
# File 'lib/ebay_trader/request.rb', line 31

def response_hash
  @response_hash
end

#response_timeObject (readonly)

Returns the value of attribute response_time.



39
40
41
# File 'lib/ebay_trader/request.rb', line 39

def response_time
  @response_time
end

#skip_type_castingObject (readonly)

Returns the value of attribute skip_type_casting.



32
33
34
# File 'lib/ebay_trader/request.rb', line 32

def skip_type_casting
  @skip_type_casting
end

#xml_requestObject (readonly)

Returns the value of attribute xml_request.



35
36
37
# File 'lib/ebay_trader/request.rb', line 35

def xml_request
  @xml_request
end

#xml_responseObject (readonly)

Returns the value of attribute xml_response.



36
37
38
# File 'lib/ebay_trader/request.rb', line 36

def xml_response
  @xml_response
end

#xml_tab_widthObject (readonly)

Returns the value of attribute xml_tab_width.



34
35
36
# File 'lib/ebay_trader/request.rb', line 34

def xml_tab_width
  @xml_tab_width
end

Instance Method Details

#deep_find(path, default = nil) ⇒ Array

Recursively deep search through the #response_hash tree and return the first value matching the given path of node names. If path cannot be matched the value of default is returned.

Parameters:

  • path (Array [String|Symbol])

    an array of the keys defining the path to the node of interest.

  • default (Object) (defaults to: nil)

    the value to be returned if path cannot be matched.

Returns:

  • (Array)

    the first value found in path, or default.



231
232
233
# File 'lib/ebay_trader/request.rb', line 231

def deep_find(path, default = nil)
  @response_hash.deep_find(path, default)
end

#errorsArray[Error]

Get an array of Errors, excluding #warnings. This will be an empty array if there are no errors.

Returns:

  • (Array[Error])

    which have a severity_code of ‘Error’.



197
198
199
# File 'lib/ebay_trader/request.rb', line 197

def errors
  @errors.select { |error| error.error? }
end

#errors_and_warningsArray[Error]

Get an array of all #errors and #warnings.

Returns:



185
186
187
# File 'lib/ebay_trader/request.rb', line 185

def errors_and_warnings
  @errors
end

#failure?Boolean

Determine if this request has failed. This should return the opposite of #success?

Returns:

  • (Boolean)


166
167
168
# File 'lib/ebay_trader/request.rb', line 166

def failure?
  deep_find(:ack, '').downcase.eql?('failure')
end

#has_errors?Boolean

Determine if this request has generated any #errors, excluding #warnings.

Returns:

  • (Boolean)

    true if any errors present.



191
192
193
# File 'lib/ebay_trader/request.rb', line 191

def has_errors?
  errors.count > 0
end

#has_errors_or_warnings?Boolean

Determine if this request has generated any #errors or #warnings.

Returns:

  • (Boolean)

    true if errors or warnings present.



179
180
181
# File 'lib/ebay_trader/request.rb', line 179

def has_errors_or_warnings?
  has_errors? || has_warnings?
end

#has_warnings?Boolean

Determine if this request has generated any #warnings.

Returns:

  • (Boolean)

    true if warnings present.



203
204
205
# File 'lib/ebay_trader/request.rb', line 203

def has_warnings?
  warnings.count > 0
end

#partial_failure?Boolean

Determine if this response has partially failed. This eBay response is somewhat ambiguous, but generally means the request was processed by eBay, but warnings were generated.

Returns:

  • (Boolean)


173
174
175
# File 'lib/ebay_trader/request.rb', line 173

def partial_failure?
  deep_find(:ack, '').downcase.eql?('partialfailure')
end

#success?Boolean

Determine if this request has been successful. This should return the opposite of #failure?

Returns:

  • (Boolean)


160
161
162
# File 'lib/ebay_trader/request.rb', line 160

def success?
  deep_find(:ack, '').downcase.eql?('success')
end

#timestampTime

Get the timestamp of the response returned by eBay API. The timestamp indicates the time when eBay processed the request; it does not necessarily indicate the current eBay official eBay time. In particular, calls like GetCategories can return a cached response, so the time stamp may not be current.

Returns:

  • (Time)

    the response timestamp.



221
222
223
# File 'lib/ebay_trader/request.rb', line 221

def timestamp
  deep_find :timestamp
end

#to_json_sString

Get a String representation of the XML data hash in JSON notation.

Returns:

  • (String)

    pretty printed JSON.



251
252
253
254
# File 'lib/ebay_trader/request.rb', line 251

def to_json_s
  require 'json' unless defined? JSON
  puts JSON.pretty_generate(JSON.parse(@response_hash.to_json))
end

#to_s(indent = xml_tab_width) ⇒ String

Get a String representation of the response XML with indentation.

Returns:

  • (String)

    the response XML.



237
238
239
240
241
242
243
244
245
246
247
# File 'lib/ebay_trader/request.rb', line 237

def to_s(indent = xml_tab_width)
  xml = ''
  if defined? Ox
    ox_doc = Ox.parse(xml_response)
    xml = Ox.dump(ox_doc, indent: indent)
  else
    rexml_doc = REXML::Document.new(xml_response)
    rexml_doc.write(xml, indent)
  end
  xml
end

#warningsArray[Error]

Get an array of Errors representing warnings. This will be an empty array if there are no errors.

Returns:

  • (Array[Error])

    which have a severity_code of ‘Warning’.



209
210
211
# File 'lib/ebay_trader/request.rb', line 209

def warnings
  @errors.select { |error| error.warning? }
end