# See the WARNING constant defined below for explanation module Rack::Insight module MagicInsight # A modicum of sanity SAFETY_REGEX_FILTER = (/(^_)|[=\?!~<>]|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 # Regex explanation: # Rack::Insight - We want to keep methods that come from Rack::Insight included modules # # b.to_s.length } end # 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 def _idiomatic_methods IDIOMS.select {|idiom| _sorted_methods.select { |meth| meth.to_s =~ /#{idiom}/ }.length == 2 } end def _has_idioms? !_idiomatic_methods.empty? end def _idiomatic_method(method) if self._has_idioms? && method = self._idiomatic_methods.select {|idiom| method.to_s =~ /#{idiom}/}.first method else false end end def _my_children "#{!children.empty? ? " (#{children.length} children)" : ''}" if self.respond_to?(:children) end # called by the templates 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 end end