Class: RailsErrorDashboard::Services::VariableSerializer

Inherits:
Object
  • Object
show all
Defined in:
lib/rails_error_dashboard/services/variable_serializer.rb

Overview

Pure algorithm: Serialize local variables to safe JSON-compatible hash

Handles circular references (thread-local Set of object_id), depth limiting, string truncation, and per-variable rescue. Never stores Binding objects.

Sensitive data filtering uses SensitiveDataFilter.parameter_filter (same approach as BreadcrumbCollector) — supports String, Symbol, Regexp, and Proc patterns from Rails filter_parameters.

Output format per variable:

{ type: "String", value: "hello", truncated: false }

Safety contract:

  • Per-variable rescue — one bad variable never crashes extraction

  • Thread-local circular detection Set, cleaned in ensure

  • Never raises — returns {} on total failure

Constant Summary collapse

THREAD_KEY =
:_red_variable_serializer_seen

Class Method Summary collapse

Class Method Details

.call(locals, max_count: nil, additional_filter_patterns: []) ⇒ Hash

Serialize a hash of variables to safe output

Parameters:

  • locals (Hash)

    { variable_name => raw_value }

  • max_count (Integer, nil) (defaults to: nil)

    Override max variable count (defaults to local_variable_max_count)

  • additional_filter_patterns (Array) (defaults to: [])

    Extra sensitive name patterns (e.g. instance_variable_filter_patterns)

Returns:

  • (Hash)

    { “variable_name” => { type:, value:, truncated:, filtered: } }



30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# File 'lib/rails_error_dashboard/services/variable_serializer.rb', line 30

def self.call(locals, max_count: nil, additional_filter_patterns: [])
  return {} unless locals.is_a?(Hash) && locals.any?

  config = RailsErrorDashboard.configuration
  max_count ||= config.local_variable_max_count || 15

  # Thread-local circular reference tracking
  Thread.current[THREAD_KEY] = Set.new

  result = {}
  locals.first(max_count).each do |name, value|
    name_str = name.to_s
    result[name_str] = serialize_variable(name_str, value, config)
  end

  filter_serialized(result, additional_filter_patterns: additional_filter_patterns)
rescue => e
  RailsErrorDashboard::Logger.debug("[RailsErrorDashboard] VariableSerializer.call failed: #{e.message}")
  {}
ensure
  Thread.current[THREAD_KEY] = nil
end