Feb 2

Improving your exception backtrace with Ruby DSLs

Category: Programming, Ruby

One issue with a Domain Specific Language in any language is that the error messages from the actual language tend to ruin the illusion of a custom language. In ruby a stack trace with a million “method_missing” calls can be confusing.
So what can you do? Edit and filter the backtrace.

The exception backtrace method returns an array of strings of the “filename:linenumber: in method” format you see when ruby prints the backtrace. By selectively removing or editing entries in the backtrace based on filename, method, etc you can make your exceptions clearer.

class MyDSL
  def initialize &block
    #remove all stack info from the DSL infrastructure itself
    #unless the exception was generated in the DSL infrastructure
    begin
      instance_eval &block
    rescue
      $!.backtrace.collect!{ |line| line.scan(__FILE__) > 0 ? nil : line}.compact! unless backtrace[0].scan(__FILE__) > 0
      raise
    end
  end
 
  def method_missing name, *args, &block
    ...
    run_block_and_markup_exceptions "some state info of use", &block
    ...
  end
 
  #run the block and if it raises an exception add custom
  #text to the bit of the back trace associated with it
  def run_block_and_markup_exceptions state_info, &block
    begin
      instance_eval &block
    rescue
      $!.backtrace.collect!{|line| line.scan("#{block.source_location[0]}:#{block.source_location[1]}").size > 0 ? line + state_info : line}
      raise
    end
  end
end
Comments are off for this post

Comments are closed.