Module: Api2Convert::Support::Data

Defined in:
lib/api2convert/support/data.rb

Overview

Typed, null-safe accessors over decoded JSON.

Mirrors the PHP SDK's Support\Data helper: model hydration stays free of scattered casts and, crucially, never raises on a surprising payload — a missing or wrong-typed field falls back to a sensible default. Internal helper, not part of the public API.

Class Method Summary collapse

Class Method Details

.as_bool(value, default = false) ⇒ Object



54
55
56
# File 'lib/api2convert/support/data.rb', line 54

def as_bool(value, default = false)
  [true, false].include?(value) ? value : default
end

.as_list(value) ⇒ Object

Return a list of values: an Array passes through; a Hash is reduced to its values (mirrors PHP array_values); anything else yields [].



65
66
67
68
69
70
# File 'lib/api2convert/support/data.rb', line 65

def as_list(value)
  return value if value.is_a?(Array)
  return value.values if value.is_a?(Hash)

  []
end

.as_object(value) ⇒ Object

Return value when it is a Hash (a JSON object), else an empty Hash.



59
60
61
# File 'lib/api2convert/support/data.rb', line 59

def as_object(value)
  value.is_a?(Hash) ? value : {}
end

.as_str(value, default = "") ⇒ Object

Return value when it is a real String, else default. Does not stringify ints/floats/bools — only genuine strings pass through.



16
17
18
# File 'lib/api2convert/support/data.rb', line 16

def as_str(value, default = "")
  value.is_a?(String) ? value : default
end

.encode_segment(value) ⇒ Object

Percent-encode a value for use as a single URL path segment.

A job/preset id or a stats date/filter is interpolated into the request path; a value carrying /, ?, #, a space or any other reserved character (e.g. all/../contracts) must be encoded so it can never break out of its segment or forge a different path. Only the RFC 3986 unreserved set survives; everything else becomes %XX over the UTF-8 bytes (mirrors Node's encodeURIComponent / Go's url.PathEscape).



91
92
93
# File 'lib/api2convert/support/data.rb', line 91

def encode_segment(value)
  value.to_s.b.gsub(/[^A-Za-z0-9\-_.~]/n) { |byte| format("%%%02X", byte.ord) }
end

.map_objects(value) ⇒ Object

Build a model from each Hash element of value; skip non-Hash elements.



73
74
75
76
77
# File 'lib/api2convert/support/data.rb', line 73

def map_objects(value)
  as_list(value).each_with_object([]) do |item, acc|
    acc << yield(item) if item.is_a?(Hash)
  end
end

.nullable_int(value) ⇒ Object

Coerce numeric values to Integer (truncating toward zero), else nil.

+true+/+false+ are rejected (they must not become 1/0). Numeric strings and floats are truncated ("3.9" -> 3), matching PHP's (int) cast.



28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
# File 'lib/api2convert/support/data.rb', line 28

def nullable_int(value)
  return nil if [true, false].include?(value)
  return value if value.is_a?(Integer)

  if value.is_a?(Float)
    return nil unless value.finite?

    return value.to_i
  end
  if value.is_a?(String)
    begin
      parsed = Float(value)
    rescue ArgumentError, TypeError
      return nil
    end
    # A numeric string that overflows Float to +/-Infinity (e.g. "1e400")
    # must fall back to nil, not raise: Float::INFINITY.to_i / NAN.to_i throw
    # FloatDomainError, and this helper must NEVER raise on a hostile payload
    # (mirrors the Float branch's finite? guard above).
    return nil unless parsed.finite?

    return parsed.to_i
  end
  nil
end

.nullable_str(value) ⇒ Object



20
21
22
# File 'lib/api2convert/support/data.rb', line 20

def nullable_str(value)
  value.is_a?(String) ? value : nil
end

.str_list(value) ⇒ Object



79
80
81
# File 'lib/api2convert/support/data.rb', line 79

def str_list(value)
  as_list(value).grep(String)
end