Add HTTP core: Faraday connection, error mapping, response wrapper, pagination, and OAuth2
This commit is contained in:
@@ -0,0 +1,82 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Fiken
|
||||
# A lightweight, read-only wrapper around a JSON response body.
|
||||
#
|
||||
# Gives both dot-access and hash-access, built recursively:
|
||||
#
|
||||
# invoice = Fiken::Object.new("invoiceNumber" => 5, "lines" => [{ "vat" => 25 }])
|
||||
# invoice.invoice_number # => 5 (also: invoice.invoiceNumber)
|
||||
# invoice[:invoiceNumber] # => 5
|
||||
# invoice.lines.first.vat # => 25
|
||||
class Object
|
||||
def initialize(attributes = {})
|
||||
@attributes = {}
|
||||
(attributes || {}).each { |key, value| @attributes[key.to_sym] = wrap(value) }
|
||||
end
|
||||
|
||||
def [](key)
|
||||
@attributes[normalize(key)]
|
||||
end
|
||||
|
||||
def key?(key)
|
||||
@attributes.key?(normalize(key))
|
||||
end
|
||||
|
||||
def keys
|
||||
@attributes.keys
|
||||
end
|
||||
|
||||
def to_h
|
||||
@attributes.transform_values { |value| unwrap(value) }
|
||||
end
|
||||
alias to_hash to_h
|
||||
|
||||
def ==(other)
|
||||
other.is_a?(Object) && other.to_h == to_h
|
||||
end
|
||||
|
||||
def respond_to_missing?(name, include_private = false)
|
||||
@attributes.key?(normalize(name)) || super
|
||||
end
|
||||
|
||||
def method_missing(name, *args)
|
||||
key = normalize(name)
|
||||
return @attributes[key] if @attributes.key?(key)
|
||||
|
||||
super
|
||||
end
|
||||
|
||||
def inspect
|
||||
"#<Fiken::Object #{@attributes.map { |k, v| "#{k}=#{v.inspect}" }.join(', ')}>"
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Accepts both :invoiceNumber and :invoice_number, mapping snake_case to the
|
||||
# camelCase keys Fiken returns.
|
||||
def normalize(key)
|
||||
sym = key.to_sym
|
||||
return sym if @attributes.key?(sym)
|
||||
|
||||
camel = key.to_s.gsub(/_([a-z])/) { Regexp.last_match(1).upcase }.to_sym
|
||||
@attributes.key?(camel) ? camel : sym
|
||||
end
|
||||
|
||||
def wrap(value)
|
||||
case value
|
||||
when Hash then Object.new(value)
|
||||
when Array then value.map { |element| wrap(element) }
|
||||
else value
|
||||
end
|
||||
end
|
||||
|
||||
def unwrap(value)
|
||||
case value
|
||||
when Object then value.to_h
|
||||
when Array then value.map { |element| unwrap(element) }
|
||||
else value
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user