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.



27
28
29
30
# File 'lib/rspec/support/object_formatter.rb', line 27

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.



11
12
13
# File 'lib/rspec/support/object_formatter.rb', line 11

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



15
16
17
# File 'lib/rspec/support/object_formatter.rb', line 15

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.



19
20
21
# File 'lib/rspec/support/object_formatter.rb', line 19

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.



23
24
25
# File 'lib/rspec/support/object_formatter.rb', line 23

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.



32
33
34
35
36
37
38
39
40
41
42
43
44
45
# File 'lib/rspec/support/object_formatter.rb', line 32

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.



68
69
70
71
72
# File 'lib/rspec/support/object_formatter.rb', line 68

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.



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

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.



56
57
58
59
60
61
62
63
64
65
66
# File 'lib/rspec/support/object_formatter.rb', line 56

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.



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

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)


111
112
113
# File 'lib/rspec/support/object_formatter.rb', line 111

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.



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

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.



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

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