Module: VisionAPI::Result
- Defined in:
- lib/vision_api/result.rb
Overview
Helpers for reading a result.
None of this is required — res["total"]["value"] is a perfectly good way to read a field, and responses stay plain hashes. These exist because three rules trip people up often enough to be worth a method:
- every scalar is wrapped in {"value", "confidence"};
- a preset response contains every field of the preset, absent ones as
nil; - a line-item array is a bare array whose cells are wrapped individually — the array itself has no confidence, each cell has its own.
Constant Summary collapse
- ORDER =
{ "low" => 0, "mid" => 1, "high" => 2 }.freeze
Class Method Summary collapse
-
.at_least?(node, level) ⇒ Boolean
Whether the field's confidence is at least
level. -
.below_confidence(result, level) ⇒ Object
The scalar fields found but below
level— your review queue. -
.field(result, name) ⇒ Hash?
The wrapped scalar, or nil when the result has no such field.
-
.field?(node) ⇒ Boolean
Whether the node is a wrapped scalar rather than rows or a block.
-
.missing(result) ⇒ Array<String>
The fields that came back empty.
-
.present(result) ⇒ Array<String>
The fields the document actually carried.
-
.rows(result, name) ⇒ Array<Hash>
A line-item array;
[]when absent or the document had no lines. -
.rows?(node) ⇒ Boolean
Whether the node is a line-item / repeated-block array.
-
.unwrap(result, drop_null: false) ⇒ Hash
Drops the wrappers, recursively.
-
.value(result, name, default = nil) ⇒ Object
A scalar field's value directly.
Class Method Details
.at_least?(node, level) ⇒ Boolean
Returns whether the field's confidence is at least level.
95 96 97 98 99 |
# File 'lib/vision_api/result.rb', line 95 def at_least?(node, level) return false unless field?(node) ORDER.fetch(node["confidence"], 0) >= ORDER.fetch(level.to_s) end |
.below_confidence(result, level) ⇒ Object
The scalar fields found but below level — your review queue.
Extract at the default min_confidence: "low" so nothing is silently dropped, then route what came back weak to a human instead of trusting it.
105 106 107 108 109 |
# File 'lib/vision_api/result.rb', line 105 def below_confidence(result, level) (result || {}).filter_map do |key, node| key if field?(node) && !node["value"].nil? && !at_least?(node, level) end end |
.field(result, name) ⇒ Hash?
Returns the wrapped scalar, or nil when the result has no such field.
54 55 56 57 |
# File 'lib/vision_api/result.rb', line 54 def field(result, name) node = (result || {})[name.to_s] field?(node) ? node : nil end |
.field?(node) ⇒ Boolean
Returns whether the node is a wrapped scalar rather than rows or a block.
20 21 22 |
# File 'lib/vision_api/result.rb', line 20 def field?(node) node.is_a?(Hash) && node.key?("value") && node.key?("confidence") end |
.missing(result) ⇒ Array<String>
Returns the fields that came back empty.
89 90 91 92 |
# File 'lib/vision_api/result.rb', line 89 def missing(result) found = present(result) (result || {}).keys.reject { |key| found.include?(key) } end |
.present(result) ⇒ Array<String>
Returns the fields the document actually carried.
76 77 78 79 80 81 82 83 84 85 86 |
# File 'lib/vision_api/result.rb', line 76 def present(result) (result || {}).filter_map do |key, node| if rows?(node) key unless node.empty? elsif field?(node) key unless node["value"].nil? else key end end end |
.rows(result, name) ⇒ Array<Hash>
Returns a line-item array; [] when absent or the document had no lines.
70 71 72 73 |
# File 'lib/vision_api/result.rb', line 70 def rows(result, name) node = (result || {})[name.to_s] rows?(node) ? node : [] end |
.rows?(node) ⇒ Boolean
Returns whether the node is a line-item / repeated-block array.
25 26 27 |
# File 'lib/vision_api/result.rb', line 25 def rows?(node) node.is_a?(Array) end |
.unwrap(result, drop_null: false) ⇒ Hash
Drops the wrappers, recursively.
unwrap("total" => {"value" => 12, "confidence" => "high"}) # => {"total" => 12}
Absent fields stay as nil, because "the preset has this field and the document did
not carry it" is information. Pass drop_null: true for only what was found.
38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
# File 'lib/vision_api/result.rb', line 38 def unwrap(result, drop_null: false) (result || {}).each_with_object({}) do |(key, node), out| if rows?(node) unwrapped = node.map { |row| unwrap(row, drop_null: drop_null) } out[key] = unwrapped unless drop_null && unwrapped.empty? elsif field?(node) next if drop_null && node["value"].nil? out[key] = node["value"] elsif node.is_a?(Hash) out[key] = unwrap(node, drop_null: drop_null) end end end |
.value(result, name, default = nil) ⇒ Object
A scalar field's value directly.
Returns default when the field is absent from the schema or present with a null
value — collapsing the two on purpose, for the common case where you only want the
number.
64 65 66 67 |
# File 'lib/vision_api/result.rb', line 64 def value(result, name, default = nil) node = field(result, name) node.nil? || node["value"].nil? ? default : node["value"] end |