[code] Example of creating your own Exception subclasses

Prompted by a question (over at SCF,) about using a SystemExit exception (fired by exit(),) to bail out of an input handling routine.

The main answer is: I know of no good use for exit() in an embedded Ruby subprocess.

… and a better solution is to use custom exception subclasses (usually of RuntimeError.)

Custom_Exception_SubClasses.rb (1.8 KB)

# encoding : UTF-8

# A simple example of creating your own Exception
#  sub-classes inside your own namespace modules.
#
# fail() is an alias for raise(), and most coding style guides
# prefer that fail() is used when first causing an exception,
# and raise() is used when re-raising a current exception within
# a rescue block.

module Author # <--<<< Change to unique toplevel namespace module.

  module SomeParticularPlugin

    VERSION = '1.0.0'
    
    InputCancellation = Class.new(RuntimeError)
    InvalidSelection  = Class.new(RuntimeError)
    NoGroupsSelected  = Class.new(RuntimeError)

    # In this module we assume that the module variables: @@prompts,
    #  @@defaults, @@choices & @@caption have already been defined.

    def get_input(selection_set)
      
      # First, make a decision about the selection set:
      if selection_set.empty?
        fail(InvalidSelection,"selection is empty!")
      elsif !selection_set.single_object?
        fail(InvalidSelection,"selection not single object!")
      else
        grps = selection_set.grep(Sketchup::Group)
        if grps.empty?
          fail(NoGroupsSelected,"no groups are selected!")
        end
      end

      data = inputbox(@@prompts,@@defaults,@@choices,@@caption)
      # false if the user cancels
      fail(InputCancellation,"user cancelled") if !data
      # otherwise data is an array of values

    rescue InputCancellation => err
      UI.messagebox("Stop: #{err.message}")
      return nil
    rescue InvalidSelection => err
      UI.messagebox("Selection Error: #{err.message}")
      return false
    rescue => err # any other exception
      # recover gracefully
      UI.messagebox("Error: #{err.message}")
      return false
    else # no errors
      # code to execute when input is valid
      return data
    end ###

  end # specific plugin module
end # outermost namespace module

I just noticed an error, although the example should still work.

Line 38 was meant to be:

      data = UI.inputbox(@@prompts,@@defaults,@@choices,@@caption)

Currently it is:

      data = inputbox(@@prompts,@@defaults,@@choices,@@caption)

which uses the global inputbox() retry wrapper method defined in “Tools/sketchup.rb”. So then the “sketchup.rb” file must be loaded first.

If y’all prefer, you can call the UI.inputbox() module method directly and bypass the retry wrapper.