Class: Arafa::Airtime::Base

Inherits:
Object
  • Object
show all
Extended by:
Dry::Initializer
Defined in:
lib/arafa/airtime/base.rb

Overview

Abstract superclass for airtime adapters (Airtime::Wasiliana, Airtime::AfricasTalking). Mirrors Providers::Base's pattern (contract-then-HTTP-call #send, shared Faraday connection) but with an airtime-shaped payload: phone_number/currency_code/amount applied to every recipient in the batch, rather than to/text/from.

Subclasses implement #endpoint, #headers, #build_payload, and #parse_response, and set a CONTRACT constant (a Dry::Validation::Contract, built on Contracts::AirtimeContract).

Constant Summary collapse

PHONE_NUMBER_TYPE =

Wraps a scalar phone_number: into an Array before per-element PhoneNumber coercion, same as Providers::Base::TO_TYPE.

Types::Array.of(Types::PhoneNumber).constructor { |value| Array(value) }

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.connectionObject

Reuses Providers::Base's Faraday connection (retry, JSON, logger with apiKey redaction) rather than building a second one.



45
46
47
# File 'lib/arafa/airtime/base.rb', line 45

def connection
  Providers::Base.connection
end

.send(*args, **kwargs) ⇒ Object

Shortcut for new(**kwargs).send, matching Providers::Base.send.



37
38
39
40
41
# File 'lib/arafa/airtime/base.rb', line 37

def send(*args, **kwargs)
  return super if args.any? || kwargs.empty?

  new(**kwargs).send
end

Instance Method Details

#build_payloadObject

Raises:

  • (NotImplementedError)


77
78
79
# File 'lib/arafa/airtime/base.rb', line 77

def build_payload
  raise NotImplementedError, "#{self.class} must implement #build_payload"
end

#connectionObject



65
66
67
# File 'lib/arafa/airtime/base.rb', line 65

def connection
  self.class.connection
end

#endpointObject

Raises:

  • (NotImplementedError)


69
70
71
# File 'lib/arafa/airtime/base.rb', line 69

def endpoint
  raise NotImplementedError, "#{self.class} must implement #endpoint"
end

#headersObject

Raises:

  • (NotImplementedError)


73
74
75
# File 'lib/arafa/airtime/base.rb', line 73

def headers
  raise NotImplementedError, "#{self.class} must implement #headers"
end

#parse_response(_response) ⇒ Object

Raises:

  • (NotImplementedError)


81
82
83
# File 'lib/arafa/airtime/base.rb', line 81

def parse_response(_response)
  raise NotImplementedError, "#{self.class} must implement #parse_response"
end

#send(*args, **kwargs) ⇒ Object

Contract → HTTP call → response parsing. Returns a Dry::Monads::Result: Success(SendResult) or Failure(Arafa::Error subclass).



53
54
55
56
57
58
59
60
61
62
63
# File 'lib/arafa/airtime/base.rb', line 53

def send(*args, **kwargs)
  return super if args.any? || kwargs.any?

  validation = validate_contract
  return validation if validation.failure?

  response = connection.post(endpoint, build_payload, headers)
  parse_response(response)
rescue Faraday::ConnectionFailed, Faraday::TimeoutError => e
  Failure(Arafa::NetworkError.new(e.message))
end