Just a quick question. I cant find it in the documentation.
If I use a standard begin ... rescue, how do I print all the errors or stack trace into the rescue?
e.g.:
begin
do x
rescue
puts errors
end
Any ideas?
There are at least two ways that I know of to get the error. The first is using a global variable: $! which is always set to the last error that occurred. The second is by explicitly capturing the error when you rescue:
begin
# do something that fails...
rescue => error
# error and $! are equivalent here
end
Either one will let you inspect or print out the backtrace using either:
$!.backtrace # => array of backtrace steps
error.backtrace # => same error
Related
Does anyone know how to rescue this ActiveRecord::StatementInvalid error in rails? The console displays "PG::InvalidTextRepresentation: ERROR: invalid input syntax for integer...". I've tried inserting a pry into the rescue block, but it's never called.
if (resource_params[:term].present?)
begin
key = resource_params[:term]
scope = scope.where("id = ? OR item_type = ? OR item_id = ? OR event = ? OR object ILIKE ?", key, key, key, key, "%#{key}%")
rescue
# handle error
end
end
Please note that I know how to prevent the error from occurring (i.e. need to convert the key to type integer for the id columns). But, I'm trying to understand why it never reaches the rescue block.
UPDATE: my initial post contained a syntax error (namely: rescue e => error) as others correctly pointed out. i'm still receiving the same error without the syntax error; i've update the code to remove the incorrect syntax.
This isn't the correct syntax for rescue:
rescue e => error
if I try and use this I get undefined local variable or method 'e'
The standard way to rescue a specific error class is to use:
rescue ActiveRecord::StatementInvalid => e
To do a "naked rescue" (which is often advised against), leave out the class name:
rescue => e
Note that in all these cases the => e can be left out if you don't need a variable pointing to the error object.
rescue ActiveRecord::StatementInvalid => e is the right syntax and should work fine, but also keep in mind that exception should actually be raised within that block.
rails executes a query when we actually try using its output(for example rendering page where we are displaying output of a query).
The following function might return a null value hence I want to use the exception flow. Can someone direct me to the correct way to do it because right now I am getting the error.
syntax error, unexpected keyword_else, expecting keyword_end else
def value_from_table1(field, key)
begin
##connection.query("SELECT #{field} FROM table1 Where key = #{key} ").each do |row|
rescue Exception=>e
puts e
else
return row[field]
end
end
end
You are passing a block to Enumerator#each which introduces a new scope, so you need to put begin as a start of exception block inside.
If you also need handle exceptions of ##connection.query, just put rescue after do-end block of .each. begin is implicit at start of method's body.
First, rescuing from Exception is always a bad idea, see Why is it a bad style to `rescue Exception => e` in Ruby? for details.
Second a begin rescue block always has to have a closing end, else is only possible after an if before
begin
# ...
rescue StandardError => e
# ...
end
Third as already said by Justin Turner in the comment, just passing a value to the DB like that makes it prone to SQL injections. Is there any reason you don't use ActiveRecord but want direct DB access?
Overall there are so many issues with this short piece of code, I would suggest to read http://guides.rubyonrails.org/ to better understand what is going on.
I am saving data to a table.
Question
title:string
author_id:integer
description:text
upvotes:integer
If a "question.upvotes" value is 1000000000000000000000, it will cause an error since it can't be saved to the "integer" type column.
How can I suppress this error? I want my program to continue running, even though the record failed to save.
I tried this, but it doesn't suppress the error:
... some code
if my_question.save
end
some more code...
Perhaps just pin that value to the biggest possible value? Add something like this to your Question model:
# app/models/question.rb
UPVOTE_MAX_VALUE = 2_147_483_647 # integer max value in postgresql
before_validation :check_upvote_max_size
private
def check_upvotes_max_size
self.upvotes = UPVOTE_MAX_VALUE if upvotes > UPVOTE_MAX_VALUE
end
... some code
begin
if my_question.save
...
end
rescue
# error handling
end
some more code ...
You receive ActiveRecord::StatementInvalid: PG::NumericValueOutOfRange: ERROR: integer out of range error. If you want to catch exactly this error, you can specify this directly:
rescue ActiveRecord::StatementInvalid
also you can add a block which will be always executed with
ensure
You can find more about exceptions handling here / And see exceptions hierarchy here
The following code in my Ruby on Rails application:
def test
begin
puts 'a'
authenticate_user!
puts 'b'
rescue Exception => e
puts 'c'
ensure
puts 'd'
end
puts 'e'
end
where:
test is a controller in Ruby on Rails
authenticate_user! is a function from the devise Ruby library
the result of accessing this is a HTTP 401
prints:
a
d
To me, this indicates that authenticate_user! has thrown some kind of exception, but we weren't able to catch it. How is this possible?
I also tried the following rescue blocks:
rescue Object => e
puts 'c'
rescue e
puts 'c'
rescue
puts 'c'
There are two types of error-handling flow in Ruby.
The most commonly used, and most flexible is begin...rescue
There is also throw and catch, which is much more lightweight. Some of the Rack libraries use this mechanism.
Most importantly, and sometimes annoyingly, the mechanisms are separate, and if a library uses throw...catch for program flow, you cannot intercept the messages using begin...rescue, therefore a rescue Exception block will not get executed.
In general you should not try and intercept third-party throw/catch, unless documentation suggests that you can. That is because the library will probably have modified env to set an error message/state. Instead, look for an equivalent method that does not work with Rack errors, but returns true or false for the conditions you are checking. For instance, perhaps the method user_signed_in? would be better.
Example of how catch works in Ruby:
puts 'a'
x = catch(:mysymbol) do
puts 'b'
throw :mysymbol, 'world'
puts 'c'
end
puts "hello #{x}"
prints
a
b
hello world
I have the following code, which is meant to display a report of the state of the app when an error is encountered.
begin
... # makes calls to lower level instances
rescue
send_report
end
def send_report
str = ""
str.concat("#{$!}\n\r")
str.concat("Report ----------\n\r")
...
raise str
end
The problem is that $! is only giving me a one line error without any of the usual stack trace. An example error is:
DEBUG - undefined method `to_sym' for nil:NilClass
And this is shown without a file name or line number or any context. How do I get that added?
You can specify the variable to store the exception in (although you're right that they do get stored in $!, I prefer explicit non-global variables).
begin
# exception is raised
rescue Exception => e
str = "#{e.message}\n"
str << e.backtrace.join("\n")
raise str
end
The reason you're only getting the error is that the exception being interpolated probably calls to_s on the Exception object, which returns its message and not its backtrace.