class RSpec::Support::ObjectFormatter

Provide additional output details beyond what ‘inspect` provides when printing Time, DateTime, or BigDecimal @api private

Constants

BaseInspector
ELLIPSIS
INSPECTOR_CLASSES
InspectableItem

Attributes

Public Class Methods

Methods are deferred to a default instance of the class to maintain the interface For example, calling ObjectFormatter.format is still possible

# File rspec-support/lib/rspec/support/object_formatter.rb, line 17
def self.default_instance
  @default_instance ||= new
end
# File rspec-support/lib/rspec/support/object_formatter.rb, line 21
def self.format(object)
  default_instance.format(object)
end
# File rspec-support/lib/rspec/support/object_formatter.rb, line 29
def initialize(max_formatted_output_length=200)
  @max_formatted_output_length = max_formatted_output_length
  @current_structure_stack = []
end
# File rspec-support/lib/rspec/support/object_formatter.rb, line 25
def self.prepare_for_inspection(object)
  default_instance.prepare_for_inspection(object)
end

Public Instance Methods

# File rspec-support/lib/rspec/support/object_formatter.rb, line 34
def format(object)
  if max_formatted_output_length.nil?
    prepare_for_inspection(object).inspect
  else
    formatted_object = prepare_for_inspection(object).inspect
    if formatted_object.length < max_formatted_output_length
      formatted_object
    else
      beginning = truncate_string formatted_object, 0, max_formatted_output_length / 2
      ending = truncate_string formatted_object, -max_formatted_output_length / 2, -1
      beginning + ELLIPSIS + ending
    end
  end
end
# File rspec-support/lib/rspec/support/object_formatter.rb, line 72
def prepare_array(array)
  with_entering_structure(array) do
    array.map { |element| prepare_element(element) }
  end
end
# File rspec-support/lib/rspec/support/object_formatter.rb, line 96
def prepare_element(element)
  if recursive_structure?(element)
    case element
    when Array then InspectableItem.new('[...]')
    when Hash then InspectableItem.new('{...}')
    else raise # This won't happen
    end
  else
    prepare_for_inspection(element)
  end
end

Prepares the provided object to be formatted by wrapping it as needed in something that, when ‘inspect` is called on it, will produce the desired output.

This allows us to apply the desired formatting to hash/array data structures at any level of nesting, simply by walking that structure and replacing items with custom items that have ‘inspect` defined to return the desired output for that item. Then we can just use `Array#inspect` or `Hash#inspect` to format the entire thing.

# File rspec-support/lib/rspec/support/object_formatter.rb, line 58
def prepare_for_inspection(object)
  case object
  when Array
    prepare_array(object)
  when Hash
    prepare_hash(object)
  when Symbol
    object
  else
    inspector_class = INSPECTOR_CLASSES.find { |inspector| inspector.can_inspect?(object) }
    inspector_class.new(object, self)
  end
end
# File rspec-support/lib/rspec/support/object_formatter.rb, line 78
def prepare_hash(input_hash)
  with_entering_structure(input_hash) do
    sort_hash_keys(input_hash).inject({}) do |output_hash, key_and_value|
      key, value = key_and_value.map { |element| prepare_element(element) }
      output_hash[key] = value
      output_hash
    end
  end
end
# File rspec-support/lib/rspec/support/object_formatter.rb, line 115
def recursive_structure?(object)
  @current_structure_stack.any? { |seen_structure| seen_structure.equal?(object) }
end
# File rspec-support/lib/rspec/support/object_formatter.rb, line 88
def sort_hash_keys(input_hash)
  if input_hash.keys.all? { |k| k.is_a?(String) || k.is_a?(Symbol) }
    Hash[input_hash.sort_by { |k, _v| k.to_s }]
  else
    input_hash
  end
end
# File rspec-support/lib/rspec/support/object_formatter.rb, line 108
def with_entering_structure(structure)
  @current_structure_stack.push(structure)
  return_value = yield
  @current_structure_stack.pop
  return_value
end