Class: Scryglass::Ro

Inherits:
Object
  • Object
show all
Defined in:
lib/scryglass/ro.rb

Overview

A ro is essentially a complex wrapper for an object that deals with how it is

nested and displayed relative to other ros/objects.

Constant Summary collapse

WRAPPER_TYPES =
{
  'Hash' => '{}',
  'Array' => '[]',
  'ActiveRecord_Relation' => '<>',
  'ActiveRecord_Associations_CollectionProxy' => '‹›',
}.freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(scry_session:, val:, val_type:, parent_ro:, key:, depth:, key_value_relationship_indicator: false, special_sub_ro_type: nil) ⇒ Ro

Returns a new instance of Ro.



25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/scryglass/ro.rb', line 25

def initialize(scry_session:,
               val:,
               val_type:,
               parent_ro:,
               key:,
               depth:,
               key_value_relationship_indicator: false,
               special_sub_ro_type: nil)
  key_clip_length = Scryglass.config.tree_view_key_string_clip_length
  value_clip_length = Scryglass.config.tree_view_value_string_clip_length

  self.has_cursor = false
  self.expanded = false

  self.key_value_relationship_indicator = key_value_relationship_indicator

  ## Open up ViewWrappers and grab their objects and their custom strings
  if key.class == Scryglass::ViewWrapper
    self.key_string = key.to_s.clip_at(key_clip_length)
    self.key = key.model
  else
    # Note: `.inspect` may return *true newlines* for objects with a custom
    #   `.inspect`, which will sabotage scry's display, so we gsub thusly:
    self.key_string = key.inspect
                         .gsub("\n", "\\n")
                         .clip_at(key_clip_length)
    self.key = key
  end
  if val.class == Scryglass::ViewWrapper
    self.value_string = val.to_s.clip_at(value_clip_length)
    self.value = val.model
  else
    # Note: `.inspect` may return *true newlines* for objects with a custom
    #   `.inspect`, which will sabotage scry's display, so we gsub thusly:
    self.value_string = val.inspect
                           .gsub("\n", "\\n")
                           .clip_at(value_clip_length)
    self.value = val
  end

  self.sub_ros = []
  self.parent_ro = parent_ro
  self.val_type = val_type
  self.special_sub_ro_type = special_sub_ro_type
  self.depth = depth
  self.wrappers = WRAPPER_TYPES[value.class.to_s.split('::').last] || '?¿'

  self.lens_strings = { key: {}, value: {} }

  self.index = scry_session.all_ros.count
  scry_session.all_ros << self
  self.scry_session = scry_session
end

Instance Attribute Details

#depthObject

Returns the value of attribute depth.



14
15
16
# File 'lib/scryglass/ro.rb', line 14

def depth
  @depth
end

#expandedObject

Returns the value of attribute expanded.



14
15
16
# File 'lib/scryglass/ro.rb', line 14

def expanded
  @expanded
end

#has_cursorObject

Returns the value of attribute has_cursor.



14
15
16
# File 'lib/scryglass/ro.rb', line 14

def has_cursor
  @has_cursor
end

#indexObject

Returns the value of attribute index.



14
15
16
# File 'lib/scryglass/ro.rb', line 14

def index
  @index
end

#keyObject

Returns the value of attribute key.



9
10
11
# File 'lib/scryglass/ro.rb', line 9

def key
  @key
end

#key_stringObject

Returns the value of attribute key_string.



9
10
11
# File 'lib/scryglass/ro.rb', line 9

def key_string
  @key_string
end

#key_value_relationship_indicatorObject

Returns the value of attribute key_value_relationship_indicator.



9
10
11
# File 'lib/scryglass/ro.rb', line 9

def key_value_relationship_indicator
  @key_value_relationship_indicator
end

#lens_stringsObject

Returns the value of attribute lens_strings.



9
10
11
# File 'lib/scryglass/ro.rb', line 9

def lens_strings
  @lens_strings
end

#parent_roObject

Returns the value of attribute parent_ro.



14
15
16
# File 'lib/scryglass/ro.rb', line 14

def parent_ro
  @parent_ro
end

#scry_sessionObject

Returns the value of attribute scry_session.



14
15
16
# File 'lib/scryglass/ro.rb', line 14

def scry_session
  @scry_session
end

#special_sub_ro_typeObject

Returns the value of attribute special_sub_ro_type.



9
10
11
# File 'lib/scryglass/ro.rb', line 9

def special_sub_ro_type
  @special_sub_ro_type
end

#sub_rosObject

Returns the value of attribute sub_ros.



14
15
16
# File 'lib/scryglass/ro.rb', line 14

def sub_ros
  @sub_ros
end

#val_typeObject

Returns the value of attribute val_type.



9
10
11
# File 'lib/scryglass/ro.rb', line 9

def val_type
  @val_type
end

#valueObject

Returns the value of attribute value.



9
10
11
# File 'lib/scryglass/ro.rb', line 9

def value
  @value
end

#value_stringObject

Returns the value of attribute value_string.



9
10
11
# File 'lib/scryglass/ro.rb', line 9

def value_string
  @value_string
end

#wrappersObject

Returns the value of attribute wrappers.



9
10
11
# File 'lib/scryglass/ro.rb', line 9

def wrappers
  @wrappers
end

Class Method Details

.safe_quick_checkObject



338
339
340
341
342
343
344
345
346
# File 'lib/scryglass/ro.rb', line 338

def safe_quick_check
  begin
    Timeout.timeout(0.05) do
      yield
    end
  rescue
    nil
  end
end

Instance Method Details

#<=>(other) ⇒ Object

This exists so that an easy *unordered array match* can occur elsewhere.



187
188
189
190
191
192
193
# File 'lib/scryglass/ro.rb', line 187

def <=>(other)
  unless self.class == other.class
    raise ArgumentError, "Comparison of #{self.class} with #{other.class}"
  end

  object_id <=> other.object_id
end

#ar_sub_rosObject



145
146
147
# File 'lib/scryglass/ro.rb', line 145

def ar_sub_ros
  sub_ros.select { |sub_ro| sub_ro.special_sub_ro_type == :ar }
end

#bucket?Boolean

Returns:

  • (Boolean)


207
208
209
# File 'lib/scryglass/ro.rb', line 207

def bucket?
  val_type == :bucket
end

#current_subjectObject



137
138
139
# File 'lib/scryglass/ro.rb', line 137

def current_subject
  send(scry_session.current_subject_type)
end

#enum_sub_rosObject



149
150
151
# File 'lib/scryglass/ro.rb', line 149

def enum_sub_ros
  sub_ros.select { |sub_ro| sub_ro.special_sub_ro_type == :enum }
end

#iv_sub_rosObject



141
142
143
# File 'lib/scryglass/ro.rb', line 141

def iv_sub_ros
  sub_ros.select { |sub_ro| sub_ro.special_sub_ro_type == :iv }
end

#key_value_pair?Boolean

Returns:

  • (Boolean)


215
216
217
# File 'lib/scryglass/ro.rb', line 215

def key_value_pair?
  !!key_value_relationship_indicator
end

#next_ro_without_using_indexObject

(Used for recalculate_indeces after new Ros have been injected)



154
155
156
157
158
159
160
161
162
163
164
# File 'lib/scryglass/ro.rb', line 154

def next_ro_without_using_index
  return sub_ros.first if sub_ros.first
  return sibling_down if sibling_down
  return nil if top_ro?

  upward_feeler_ro = self
  until upward_feeler_ro.sibling_down || upward_feeler_ro.top_ro?
    upward_feeler_ro = upward_feeler_ro.parent_ro
  end
  upward_feeler_ro.sibling_down
end

#next_visible_ro_downObject



98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
# File 'lib/scryglass/ro.rb', line 98

def next_visible_ro_down
  raise '(Must be called on a "visible" row)' unless visible?

  first_sub_ro = sub_ros.first
  return first_sub_ro if expanded && first_sub_ro
  return nil if top_ro?

  next_sibling = sibling_down
  return next_sibling if next_sibling

  # Note: since this ro is known to be visible, all its parents are, too.
  upward_feeler_ro = self.parent_ro
  parents_lower_sibling = upward_feeler_ro.sibling_down
  until parents_lower_sibling || upward_feeler_ro.top_ro?
    upward_feeler_ro = upward_feeler_ro.parent_ro
    parents_lower_sibling = upward_feeler_ro.sibling_down
  end

  parents_lower_sibling
end

#next_visible_ro_upObject



119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
# File 'lib/scryglass/ro.rb', line 119

def next_visible_ro_up
  raise '(Must be called on a "visible" row)' unless visible?

  return nil if top_ro?

  next_sibling_up = sibling_up

  # Note: since this ro is known to be visible, all its parents are, too.
  return parent_ro unless next_sibling_up

  downward_feeler_ro = next_sibling_up
  while downward_feeler_ro.expanded && downward_feeler_ro.sub_ros.any?
    downward_feeler_ro = downward_feeler_ro.sub_ros.last
  end

  downward_feeler_ro
end

#nugget?Boolean

Returns:

  • (Boolean)


211
212
213
# File 'lib/scryglass/ro.rb', line 211

def nugget?
  val_type == :nugget
end

#sibling_downObject



166
167
168
169
170
171
172
173
174
# File 'lib/scryglass/ro.rb', line 166

def sibling_down
  return nil if top_ro?

  siblings = parent_ro.sub_ros
  self_index = siblings.index(self)
  return nil if self == siblings.last

  siblings[self_index + 1]
end

#sibling_upObject



176
177
178
179
180
181
182
183
184
# File 'lib/scryglass/ro.rb', line 176

def sibling_up
  return nil if top_ro?

  siblings = parent_ro.sub_ros
  self_index = siblings.index(self)
  return nil if self_index.zero?

  siblings[self_index - 1]
end

#special_sub_rosObject



219
220
221
# File 'lib/scryglass/ro.rb', line 219

def special_sub_ros
  sub_ros.select(&:special_sub_ro_type)
end

#to_sObject



83
84
85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/scryglass/ro.rb', line 83

def to_s
  value_indicator =
    bucket? ? bucket_indicator : value_string

  key_value_spacer =
    key_value_pair? ? key_string + key_value_relationship_indicator : ''
    dot = ''
    dot = "\e[36m#{dot}\e[00m" if Scryglass.config.dot_coloring # cyan then back to *default*
  special_sub_ro_expansion_indicator =
    any_special_sub_ros? && !expanded ? dot : ' '

  left_fill_string + special_sub_ro_expansion_indicator +
    key_value_spacer + value_indicator
end

#top_ro?Boolean

Returns:

  • (Boolean)


79
80
81
# File 'lib/scryglass/ro.rb', line 79

def top_ro?
  parent_ro.nil?
end

#visible?Boolean

Returns:

  • (Boolean)


196
197
198
199
200
201
202
203
204
205
# File 'lib/scryglass/ro.rb', line 196

def visible?
  return true if top_ro?

  scanning_ro = parent_ro
  until scanning_ro.top_ro? || !scanning_ro.expanded
    scanning_ro = scanning_ro.parent_ro
  end

  scanning_ro.expanded
end