Class: RSpec::Support::ObjectFormatter Private

Inherits:
Object
  • Object
show all
Defined in:
lib/rspec/support/object_formatter.rb

Overview

This class is part of a private API. You should avoid using this class if possible, as it may be removed or be changed in the future.

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

Defined Under Namespace

Classes: BaseInspector, BigDecimalInspector, DateTimeInspector, DelegatorInspector, DescribableMatcherInspector, InspectableItem, InspectableObjectInspector, TimeInspector, UninspectableObjectInspector

Constant Summary collapse

ELLIPSIS =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

rubocop:disable Metrics/ClassLength

"..."
INSPECTOR_CLASSES =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

[
  TimeInspector,
  DateTimeInspector,
  BigDecimalInspector,
  UninspectableObjectInspector,
  DescribableMatcherInspector,
  DelegatorInspector,
  InspectableObjectInspector
].tap do |classes|
  # 2.4 has improved BigDecimal formatting so we do not need
  # to provide our own.
  # https://github.com/ruby/bigdecimal/pull/42
  classes.delete(BigDecimalInspector) if RUBY_VERSION >= '2.4'
end

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(max_formatted_output_length = 200) ⇒ ObjectFormatter

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns a new instance of ObjectFormatter.



29
30
31
32
# File '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

Instance Attribute Details

#max_formatted_output_lengthObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



13
14
15
# File 'lib/rspec/support/object_formatter.rb', line 13

def max_formatted_output_length
  @max_formatted_output_length
end

Class Method Details

.default_instanceObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

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



17
18
19
# File 'lib/rspec/support/object_formatter.rb', line 17

def self.default_instance
  @default_instance ||= new
end

.format(object) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



21
22
23
# File 'lib/rspec/support/object_formatter.rb', line 21

def self.format(object)
  default_instance.format(object)
end

.prepare_for_inspection(object) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



25
26
27
# File 'lib/rspec/support/object_formatter.rb', line 25

def self.prepare_for_inspection(object)
  default_instance.prepare_for_inspection(object)
end

Instance Method Details

#format(object) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



34
35
36
37
38
39
40
41
42
43
44
45
46
47
# File '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

#prepare_array(array) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



70
71
72
73
74
# File 'lib/rspec/support/object_formatter.rb', line 70

def prepare_array(array)
  with_entering_structure(array) do
    array.map { |element| prepare_element(element) }
  end
end

#prepare_element(element) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



94
95
96
97
98
99
100
101
102
103
104
# File 'lib/rspec/support/object_formatter.rb', line 94

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

#prepare_for_inspection(object) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

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.



58
59
60
61
62
63
64
65
66
67
68
# File '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)
  else
    inspector_class = INSPECTOR_CLASSES.find { |inspector| inspector.can_inspect?(object) }
    inspector_class.new(object, self)
  end
end

#prepare_hash(input_hash) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



76
77
78
79
80
81
82
83
84
# File 'lib/rspec/support/object_formatter.rb', line 76

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

#recursive_structure?(object) ⇒ Boolean

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns:

  • (Boolean)


113
114
115
# File 'lib/rspec/support/object_formatter.rb', line 113

def recursive_structure?(object)
  @current_structure_stack.any? { |seen_structure| seen_structure.equal?(object) }
end

#sort_hash_keys(input_hash) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



86
87
88
89
90
91
92
# File 'lib/rspec/support/object_formatter.rb', line 86

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

#with_entering_structure(structure) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



106
107
108
109
110
111
# File 'lib/rspec/support/object_formatter.rb', line 106

def with_entering_structure(structure)
  @current_structure_stack.push(structure)
  return_value = yield
  @current_structure_stack.pop
  return_value
end