2

Ruby has BEGIN {} and END {} blocks that guarantee they run before and after the main portion of code, respectively.

I have the following code:

BEGIN {
  $my_args = ARGV.dup
  ARGV.clear
} # clean up 'gets'

# For the truly paranoid in all of us
def self.run_away?
  print "You're paranoid. Exit? (Y/n) "
  ans = gets.chomp.downcase
  if ["no", "n"].include?(ans)
    puts "Alright, your call. Let's keep going."
  else
    puts "EXITING"
    log("Exiting at paranoid users request.")
    exit 3
  end
end

END {  } # do stuff here

I have a handful of error codes that I have defined in my script. I would like to be able to read the error code and print a short description based on that code. E.g. - EXITING - 3: Exit at user request instead of writing a descriptive string every time I use an exit in my code. Is there a way to do this in the END {} block? Or something else I am missing?

Edit/Note: I'm stuck with Ruby 1.8.7 and the following doesn't work: (see below)

BEGIN { puts "BEGIN block!" }

puts "Main block!"
exit 3

END {
  puts "END block!"
  puts "Current Exception: \n#{$!}"
  puts "Current Backtrace: \n#{$@}"
}

Output:

~: $ ./test.rb 
BEGIN block!
Main block!
~: $ echo $?
3
~: $

Edit #2: I had to define my END block before I exited. Thanks to @Stefan

2 Answers 2

3

Kernel#exit raises a SystemExit exception and since the global variable $! contains the current exception, you can get the exit status via $!.status:

END {
  puts "exit status: #{$!.status}"
}
exit 3

Output:

exit status: 3

From the documentation:

When an exception has been raised but not yet handled (in rescue, ensure, at_exit and END blocks) the global variable $! will contain the current exception and $@ contains the current exception’s backtrace.

Sign up to request clarification or add additional context in comments.

3 Comments

This is great and I'll definitely keep it in mind for my weekend projects, but I'm using on CentOS at work and stuck with 1.8.7. I'll edit the question. Thanks!
See my edit to see what I did. Am I messing up the implementation?
You have to define your END block before calling exit
1

A way to centralize exit message :

module Kernel
  alias :real_exit :exit

  def exit status
    puts "Hello World"
    real_exit status
  end
end

The method is just an around alias on the Kernel#exit method. Be aware that once you will have define this override, all other exit call will go through your override.

1 Comment

Yeah, I thought about this sort of an implementation. It's not ideal but may be necessary. Thanks a bunch!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.