class Symgate::Client

A generic client for the Symgate API. See the WSDL for full documentation

Attributes

account[RW]
data_required_error_retries[RW]
endpoint[RW]
key[RW]
password[RW]
savon_client[R]
savon_opts[RW]
token[RW]
user[RW]
wsdl[RW]

Public Class Methods

new(opts = {}) click to toggle source

Constructs a new client with the provided options

# File lib/symgate/client.rb, line 14
def initialize(opts = {})
  @wsdl = 'https://ws.widgitonline.com/schema/symboliser.wsdl'
  @endpoint = 'https://ws.widgitonline.com/'
  @savon_opts = {}
  @data_required_error_retries = 3
  opts.each { |k, v| instance_variable_set("@#{k}", v) }

  validate_client_options
  create_savon_client
end
savon_array(hash, key, classname = nil) click to toggle source

returns an array from 0 or more items when an array is expected. (savon returns a single value for things that can be a sequence of multiple objects) expects a hash, and a key for the array within that hash. if classname is specified, the method will return an array of objects initialised by the hash contents

# File lib/symgate/client.rb, line 30
def self.savon_array(hash, key, classname = nil)
  if hash && hash.include?(key)
    [hash[key]].flatten
  else
    []
  end.map { |v| classname ? classname.from_soap(v) : v }
end

Protected Instance Methods

arrayize_option(singular, plural, opts) click to toggle source
# File lib/symgate/client.rb, line 119
def arrayize_option(singular, plural, opts)
  return unless opts.include? singular # else nothing to do
  raise Symgate::Error, "Options can't include both #{singular} and #{plural}" if
      opts.include? plural

  opts[plural] = [opts[singular]]
  opts.delete(singular)
end
check_array_for_type(ary, type_name) click to toggle source
# File lib/symgate/client.rb, line 140
def check_array_for_type(ary, type_name)
  raise Symgate::Error, "#{ary.class.name} is not an array" unless ary.is_a? Array

  ary.each do |item|
    unless item.is_a? type_name
      raise Symgate::Error, "'#{item.class.name}' is not a #{type_name.name}"
    end
  end
end
check_for_multiple_opts(keys, opts) click to toggle source
# File lib/symgate/client.rb, line 150
def check_for_multiple_opts(keys, opts)
  raise Symgate::Error, "Supply only one of 'match' or 'entry'" if keys.all? { |k| opts.key? k }
end
check_for_unknown_opts(keys, opts) click to toggle source
# File lib/symgate/client.rb, line 134
def check_for_unknown_opts(keys, opts)
  opts.keys.each do |k|
    raise Symgate::Error, "Unknown option: #{k}" unless keys.include? k
  end
end
check_option_is_array_of(classname, key, opts) click to toggle source
# File lib/symgate/client.rb, line 128
def check_option_is_array_of(classname, key, opts)
  return unless opts.include? key
  raise Symgate::Error, "#{key} must be an array" unless opts[key].is_a? Array
  check_array_for_type(opts[key], classname)
end
create_savon_client() click to toggle source
# File lib/symgate/client.rb, line 61
def create_savon_client
  @savon_client = Savon.client(savon_opts.merge(wsdl: @wsdl, endpoint: @endpoint)) do
    endpoint(@endpoint) if @endpoint
    namespaces(Symgate::NAMESPACES)
  end
end
raise_error_on_string_response(response, response_type) click to toggle source
# File lib/symgate/client.rb, line 114
def raise_error_on_string_response(response, response_type)
  e = response.body[response_type]
  raise Symgate::Error, e unless e.to_s == ''
end
savon_creds() click to toggle source

builds a credentials object - required for all requests

# File lib/symgate/client.rb, line 69
def savon_creds
  creds = { :auth:account => @account }
  creds[:'auth:key'] = @key if @key
  creds[:'auth:user'] = savon_user if @user

  { :auth:creds => creds }
end
savon_request(method, opts = {}) { |soap| ... } click to toggle source

sends a request to the server and yields a soap block for defining the message body

# File lib/symgate/client.rb, line 87
def savon_request(method, opts = {})
  attempts = 0

  begin
    attempts += 1

    r = @savon_client.call(method) do |soap|
      yield soap if block_given?
      soap.message({}) if soap[:message].nil?
      soap[:message].merge!(savon_creds)
    end

    raise_error_on_string_response(r, "#{method}_response".to_sym) if opts[:returns_error_string]

    r
  rescue Savon::SOAPFault => e
    # Allow a configurable number of retries for a 'Data required for operation' error. This is because the
    # symboliser occasionally throw this error when it shouldn't and succeeds on retry. It's not ideal that we have
    # to rely on the fault string, however.
    if attempts < @data_required_error_retries && e.to_hash[:fault][:faultstring] == 'Data required for operation'
      retry
    end

    raise Symgate::Error.from_savon(e)
  end
end
savon_user() click to toggle source
# File lib/symgate/client.rb, line 77
def savon_user
  user = { :auth:id => @user }
  user[:'auth:password'] = @password if @password
  user[:'auth:authtoken'] = @token if @token

  user
end
validate_client_options() click to toggle source

ensures enough information has been passed to the client

# File lib/symgate/client.rb, line 41
def validate_client_options
  validate_has_account
  validate_has_key_or_user
  validate_is_passwordy
end
validate_has_account() click to toggle source
# File lib/symgate/client.rb, line 47
def validate_has_account
  raise Symgate::Error, 'No account specified' if @account.nil?
end
validate_has_key_or_user() click to toggle source
# File lib/symgate/client.rb, line 51
def validate_has_key_or_user
  raise Symgate::Error, 'No key or user specified' if @key.nil? && @user.nil?
  raise Symgate::Error, 'Both key and user were specified' if @key && @user
end
validate_is_passwordy() click to toggle source
# File lib/symgate/client.rb, line 56
def validate_is_passwordy
  raise Symgate::Error, 'You must supply one of key, password or token' unless
      [@key, @password, @token].one?
end