Module: Rack::Insight::MagicInsight

Included in:
DefaultInvocation, TemplatesPanel::Rendering
Defined in:
lib/rack/insight/magic_insight.rb

Constant Summary collapse

SAFETY_REGEX_FILTER =

A modicum of sanity

(/(^_)|[=\?!~<>]|save|record|persist|delete|destroy|add|remove|child|parent/).freeze
WARNING =
[
  "  # PROCEED CAREFULLY!",
  "  #",
  "  # Regarding classes which include this module:",
  "  #",
  "  # 1. Classes should be built specifically to be rendered by rack-insight,",
  "  #    and not have destructive methods.",
  "  # 2. ALL instance methods on the class (generally not from ancestors) will be called,",
  "  #    so if any are destructive you will cry.",
  "  # 3. Define ALL: Any instance methods that get past the safety regex filter.",
  "  # 4. Define safety regex filter: Rack::Insight::MagicInsight::SAFETY_REGEX_FILTER is",
  "  #",
  "  #    #{SAFETY_REGEX_FILTER.inspect}",
  "  #",
  "  # 5. To reiterate: all methods that do not match the above will be called.",
  "  #",
  "  # Classes that desire to be renderable by the magic_panel templates must:",
  "  #",
  "  #    include Rack::Insight::MagicInsight.",
  "  #",
  "  # 6. This gives explicit approval for rack-insight to call all the instance methods on your class,",
  "  #    including the kill_server method (if you have one)."
].freeze
ANCESTORS_FILTER =

Regex explanation:

Rack::Insight - We want to keep methods that come from Rack::Insight included modules
#<Class: - An ancestor matching this is probably from a class definition like this:
            class FooStats < Struct.new :foo, :bar
           We need to keep :foo and :bar from the anonymous Struct ancestor
/^Rack::Insight|#<Class:/.freeze
IDIOMS =
%w( backtrace time duration timing )

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.included(base) ⇒ Object



41
42
43
44
45
46
47
48
49
50
# File 'lib/rack/insight/magic_insight.rb', line 41

def self.included(base)
  # Make sure people want to eat their lunch before we serve it to them.
  # Allows Rack::Insight namespaced classes to use MagicInsight without warnings.
  if Rack::Insight::Config.config[:silence_magic_insight_warnings] || base.to_s =~ /^Rack::Insight/
    # crickets...
  else
    warn "Rack::Insight::MagicInsight has been included in #{base}.\n#{WARNING.join("\n")}"
    raise 'Checking for dupes impossible.' if base.instance_methods.include?(:dirty_ancestors)
  end
end

Instance Method Details

#_dirty_ancestorsObject



52
53
54
# File 'lib/rack/insight/magic_insight.rb', line 52

def _dirty_ancestors
  self.class.ancestors[1..-1]
end

#_dirty_methodsObject



60
61
62
# File 'lib/rack/insight/magic_insight.rb', line 60

def _dirty_methods
  self.class.instance_methods - (_filtered_ancestors.map &:instance_methods).flatten
end

#_filtered_ancestorsObject



56
57
58
# File 'lib/rack/insight/magic_insight.rb', line 56

def _filtered_ancestors
  _dirty_ancestors.select {|c| !(c.to_s =~ ANCESTORS_FILTER)}
end

#_filtered_methodsObject



64
65
66
# File 'lib/rack/insight/magic_insight.rb', line 64

def _filtered_methods
  _dirty_methods.select {|x| !(x =~ Rack::Insight::MagicInsight::SAFETY_REGEX_FILTER)}.sort
end

#_has_idioms?Boolean

Returns:

  • (Boolean)


78
79
80
# File 'lib/rack/insight/magic_insight.rb', line 78

def _has_idioms?
  !_idiomatic_methods.empty?
end

#_idiomatic_method(method) ⇒ Object



82
83
84
85
86
87
88
# File 'lib/rack/insight/magic_insight.rb', line 82

def _idiomatic_method(method)
  if self._has_idioms? && method = self._idiomatic_methods.select {|idiom| method.to_s =~ /#{idiom}/}.first
    method
  else
    false
  end
end

#_idiomatic_methodsObject

If there are two methods matching an idiom, then we only want to render one of the two. If there are more than two, then make no assumptions



74
75
76
# File 'lib/rack/insight/magic_insight.rb', line 74

def _idiomatic_methods
  IDIOMS.select {|idiom| _sorted_methods.select { |meth| meth.to_s =~ /#{idiom}/ }.length == 2 }
end

#_magic_insight_methodsObject

called by the templates



95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
# File 'lib/rack/insight/magic_insight.rb', line 95

def _magic_insight_methods
  # We want to keep the longer of the methods by num chars in the method name, because these are the ones meant for
  # humans to see (e.g. human_time, filtered_backtrace, display_time)
  sorted = _sorted_methods
  idiomatic = _idiomatic_methods
  # So we delete the shorter of the two
  idiomatic.each do |idiom|
    sorted.each_with_index do |meth, index|
      # first one found will be the shortest, so delete and move to next idiom
      if meth.to_s =~ /#{idiom}/
        sorted.delete_at(index)
        break # to idiomatic loop
      end
    end
  end
  sorted
end

#_my_childrenObject



90
91
92
# File 'lib/rack/insight/magic_insight.rb', line 90

def _my_children
  "#{!children.empty? ? " (#{children.length} children)" : ''}" if self.respond_to?(:children)
end

#_sorted_methodsObject



68
69
70
# File 'lib/rack/insight/magic_insight.rb', line 68

def _sorted_methods
  _filtered_methods.sort {|a,b| a.to_s.length <=> b.to_s.length }
end