Module: SolidLoop::ApplicationHelper
- Defined in:
- app/helpers/solid_loop/application_helper.rb
Constant Summary collapse
- INFRA_ERROR_PATTERNS =
Module-level so read models / KPIs can reuse the same rules as the view.
[ /\AHTTP \d{3}\b/, # provider returned a non-2xx envelope /\bFaraday::/, # transport / connection error class /\bJSON::ParserError\b/, # unparseable provider response body /invalid_json_after_redaction/, # OpenRouter PII-redaction mangled the body /PII detected/i, /\b(?:timed out|timeout|connection (?:refused|reset))\b/i ].freeze
- CODE_ERROR_PREFIX =
Agent-side code bugs — even when the text happens to mention "timeout" or "connection" — must NOT be mislabelled infra (e.g. a NoMethodError whose message references a
timeoutmethod). Checked before the infra patterns. /\A(?:NoMethodError|NameError|ArgumentError|TypeError|KeyError|IndexError|RuntimeError|NotImplementedError|FrozenError|ZeroDivisionError|NoMatchingPatternError)\b/
Class Method Summary collapse
Instance Method Summary collapse
-
#sl_failure_kind(loop) ⇒ Object
---- Failure classification ------------------------------------------- A loop's terminal error is captured only as a free-text
error_message(e.g. "HTTP 403: ...", "Faraday::ConnectionFailed: ...", or an agent-side exception). -
#sl_failure_reason(loop, limit: 140) ⇒ Object
A short, human failure reason for inline display / tooltips.
-
#sl_money(amount) ⇒ Object
---- Money ------------------------------------------------------------- One money formatter used everywhere in the admin so the same cost never reads as "$0.09" in one place, "$0.0248" in another and "$0.00029" in a third.
-
#sl_subject_link(loop) ⇒ Object
---- Subject linking --------------------------------------------------- A loop's polymorphic subject ("User #2") is an app record the engine can't route to.
Class Method Details
.classify_failure(error_message) ⇒ Object
62 63 64 65 66 67 68 |
# File 'app/helpers/solid_loop/application_helper.rb', line 62 def self.classify_failure() msg = .to_s.strip return :agent if msg.blank? return :agent if msg.match?(CODE_ERROR_PREFIX) INFRA_ERROR_PATTERNS.any? { |re| msg.match?(re) } ? :infra : :agent end |
Instance Method Details
#sl_failure_kind(loop) ⇒ Object
---- Failure classification -------------------------------------------
A loop's terminal error is captured only as a free-text error_message
(e.g. "HTTP 403: ...", "Faraday::ConnectionFailed: ...", or an agent-side
exception). Classify without a schema change by pattern-matching that
string: provider/transport problems (HTTP status, Faraday, JSON parse of
the wire response, PII-redaction rejection) are INFRA failures — not agent
bugs. Everything else that reached failed is an AGENT failure.
Returns :infra, :agent, or nil (loop is not failed / has no message).
41 42 43 44 45 |
# File 'app/helpers/solid_loop/application_helper.rb', line 41 def sl_failure_kind(loop) return nil unless loop.status == "failed" SolidLoop::ApplicationHelper.classify_failure(loop.) end |
#sl_failure_reason(loop, limit: 140) ⇒ Object
A short, human failure reason for inline display / tooltips. Trims the noisy body so a table cell stays readable; full text is on the loop page.
72 73 74 75 76 77 78 |
# File 'app/helpers/solid_loop/application_helper.rb', line 72 def sl_failure_reason(loop, limit: 140) msg = loop..to_s.strip return nil if msg.empty? msg = msg.gsub(/\s+/, " ") msg.length > limit ? "#{msg[0, limit - 1]}…" : msg end |
#sl_money(amount) ⇒ Object
---- Money ------------------------------------------------------------- One money formatter used everywhere in the admin so the same cost never reads as "$0.09" in one place, "$0.0248" in another and "$0.00029" in a third. Shows 2 dp for "normal" amounts but keeps enough significant figures that a sub-cent run never collapses to "$0.00".
1.2345 -> "$1.23"
0.0248 -> "$0.025"
0.00029 -> "$0.00029"
0.0 -> "$0.00"
-0.005 -> "-$0.0050"
14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
# File 'app/helpers/solid_loop/application_helper.rb', line 14 def sl_money(amount) value = amount.to_f return "$0.00" if value.zero? abs = value.abs # Default to 2 dp so "normal" money reads $0.09 / $1.23. But when 2 dp # would lose precision (0.0248 -> 0.02) OR round a real amount away to # zero (0.00029 -> 0.00), extend precision to ~2 significant figures so # sub-cent runs stay legible instead of collapsing. precision = 2 if abs < 0.1 && (abs - abs.round(2)).abs > Float::EPSILON precision = [(-Math.log10(abs)).floor + 2, 8].min end # Sign goes before the "$" (never "$-0.0050"). "#{'-' if value.negative?}$#{number_with_precision(abs, precision: precision)}" end |
#sl_subject_link(loop) ⇒ Object
---- Subject linking --------------------------------------------------- A loop's polymorphic subject ("User #2") is an app record the engine can't route to. Host apps register a resolver returning a URL (and, optionally, a richer label) so the admin can deep-link to it. When no resolver is configured we degrade to the plain "Type #id" text.
SolidLoop.subject_resolver = ->(loop) {
{ url: main_app.user_path(loop.subject_id), label: loop.subject&.name }
}
89 90 91 92 93 94 95 96 97 |
# File 'app/helpers/solid_loop/application_helper.rb', line 89 def sl_subject_link(loop) return nil if loop.subject_type.blank? && loop.subject_id.blank? resolved = sl_resolve_subject(loop) label = resolved[:label].presence || "#{loop.subject_type} ##{loop.subject_id}" url = sl_safe_subject_url(resolved[:url]) url ? link_to(label, url) : label end |