3

I know how to catch the exceptions but what we do is to put "rescue" after a suspicious section of a code. what if you had a lot functions sending a query to mysql through mysql2 gem and you want to catch their exceptions. One thing you can do is to put a "rescue" statement in each of them. but i want to do that just by one rescue statement. So I put a "rescue" in end of code and put all of code in a "begin" and "end" but it didn't work.

Here is my code and as you see there is a problem in mysql query and just because of "rescue" being end of file, it doesn't catch the exception but when I put it after that query it works.

    require 'mysql2'
require 'colored'

begin

def log(string)
  p "["+string.cyan+"]"
end

def err
  p "["+"FAIL".red+"]"
end

def done
  p "["+"DONE".red+"]"
end

class SqlClient
  def initialize()
    log "SqlClient/initialize"
    puts "Host: \n"
    @host = gets.strip
    puts "User: \n"
    @user = gets.strip
    puts "Pass: \n"
    @pass = gets.strip
    @client = Mysql2::Client.new(host: @host , username: @user , password: @pass)

  end

  def list_databases()
    puts "We are listing your databases(not just projects) \n \n \n "
    @client.query("ELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA").each do |row|
      p row["SCHEMA_NAME"]
    end

    puts "\n \n \n"

  end

end

    rescue Mysql2::Error
    err
    abort

end


    `query': You have an error in your SQL syntax; check the manual that corresponds to your 
MySQL server version for the right syntax to use near 'ELECT SCHEMA_NAME FROM 
INFORMATION_SCHEMA.SCHEMATA' at line 1 (Mysql2::Error)

I'm not looking for something like:

begin
  # my code
rescue # this line is right after the code which is going to have problem and we catch it.

end

I'm looking for something like this:

begin
  # first method
  # second method
  # thrid method
  # rest of code and etc ...
  # now this is end of file: 
rescue
end

but as you saw in my code, it didn't work.

UPDATE: I found a similar question here and it seems there will be no answer :| maybe this is a sort of ruby Weakness.

Pooya
  • 992
  • 2
  • 10
  • 31
  • Why is it so difficult to press the shift key? – ChiefTwoPencils Mar 06 '13 at 23:47
  • maybe i'm misunderstanding, but with begin-rescue-end you can put as much as you want in the begin block. – danh Mar 06 '13 at 23:49
  • If this is a Rails app, you can put a single rescue handler in your ApplicationController. I'd put a full answer with details, but since you haven't tagged Rails, I'm not sure it applies. – Jim Stewart Mar 06 '13 at 23:53
  • 1
    This is not how this works. If you put a `begin/rescue` around method definitions, you will only catch error raised during this definition. – oldergod Mar 07 '13 at 00:28
  • @oldergod isn't there any way to do what I was looking for? – Pooya Mar 07 '13 at 00:32

5 Answers5

4

if you want to see ANY error just use e for example

begin
  # your call to a method of Mysql2 gem. for example:
  client = Mysql2::Client.new(:host => "localhost", :username => "root", etc...)

rescue => e
  puts e.message
  puts e.backtrace.inspect 

end

In order to catch every exception you'd need to wrap each method call with a begin rescue end. When an exception is raised it bails out of the execution so it wouldn't hit the next methods.

To catch all errors I guess I'd do something like this. Keep in mind, this is ugly and I'd recommend for you NOT to do this, but... if you want to try, maybe try something like this:

all_errors = []

# first method you call
begin
  # some error might happen here
  first_response = Mysql2::Client.new(:host => "localhost", :username => "root", etc...)
rescue => e
  all_errors << e
end

# second method you call
begin
  # some error might happen here
  second_response = Mysql2::Client.new(:host => "localhost", :username => "root", etc...)
rescue => e
  all_errors << e
end

puts all_errors.inspect

After a quick search I've found: (http://coderrr.wordpress.com/2008/11/07/the-simple-way-to-print-exceptions-in-ruby/)

# catch all exceptions (anything that derives from Exception)
begin
  ...
rescue Exception
  puts $!, $@
end
AdamT
  • 6,405
  • 10
  • 49
  • 75
  • Maybe i didn't explain my question well. my problem is that I don't want to put rescue right after that mysql code. suppose you have 20 methods using mysql2 gem to send different queries. I don't want to put a "rescue" for each of them". I edited my post and put my code there. as you see, "rescue" is in end of file and doesn't work. – Pooya Mar 07 '13 at 00:06
  • This does not catch every exception. – oldergod Mar 07 '13 at 00:10
  • If you want to catch every exception you'd have to catch it, store it in a value and then continue with the execution. – AdamT Mar 07 '13 at 00:48
  • @NewB I'm looking for something exactly vice versa ! as you see, you put rescue for everything! I want to put one rescue for everything! catch the exception wherever it occurs! – Pooya Mar 07 '13 at 00:57
  • You would need to make sure that you catch the sort of exceptions raised by the gem. (Regarding my update) – AdamT Mar 07 '13 at 01:01
  • @NewB I put the updated code ( from "rescue" to end) in the end of file and still I get mysql error: ` `query': You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'ELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA' at line 1 (Mysql2::Error) ` – Pooya Mar 07 '13 at 01:07
2

You could use an at_exit handler, which has access to the last exception in $!

like

 at_exit {
   puts "the exception that killed us is", $! 
 }

If you want to catch Exceptions "as soon as they occur" (not after they're caught) you could use ruby's "debug mode" (which outputs messages when they occur to the console) or ruby-debug see Is there any way to start the Ruby debugger on exception?

Community
  • 1
  • 1
rogerdpack
  • 62,887
  • 36
  • 269
  • 388
0

Just wrap all your code in:

begin

   #yourcode
   #as much as you want
rescue 

end 
BlackHatSamurai
  • 23,275
  • 22
  • 95
  • 156
  • I edited my post and put my code there. I had tested your solution before. it doesn't work. – Pooya Mar 06 '13 at 23:58
0

Nobody seemed to notice it but using rescue without a class will catch all StandardError and there are so much more.

If you want to catch ALL exceptions you need to do

begin
  # your code where you call SqlClient.new etc
rescue Exception => e
  puts "error raised"
  puts [e, e.backtrace].flatten.join("\n")
end

List of all error classes:

Exception
 NoMemoryError
 ScriptError
   LoadError
   NotImplementedError
   SyntaxError
 SignalException
   Interrupt
 StandardError
   ArgumentError
   IOError
     EOFError
   IndexError
   LocalJumpError
   NameError
     NoMethodError
   RangeError
     FloatDomainError
   RegexpError
   RuntimeError
   SecurityError
   SystemCallError
   SystemStackError
   ThreadError
   TypeError
   ZeroDivisionError
 SystemExit
 fatal
oldergod
  • 15,033
  • 7
  • 62
  • 88
0

have you tried adding an at_exit method in your class? This would allow you to do something when ruby is exiting. like in this article.

Ruby at_exit

or

From Ruby 2.0 API Docs

However beware of cleverly rescuing from an exception!

You'll start pulling your hair out down the road (or another dev will) when you try to figure out why your code isn't failing when it should be failing. I prefer to fail massively with a bright shiny sign saying the code failed here! hehe.

Good luck!

Community
  • 1
  • 1
engineerDave
  • 3,887
  • 26
  • 28
  • I put it right after the wrong query at first and it didn't work. after that i put it in end of file and didn't work again! – Pooya Mar 07 '13 at 00:26