83 lines
2.0 KiB
Ruby
83 lines
2.0 KiB
Ruby
# 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
|