How to Rescue ActiveRecord::StatementInvalid Error - ruby-on-rails

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).

Related

TypeError: no implicit conversion of Capybara::ElementNotFound into String

I have some pretty basic code:
def select_author_name(comment)
selector = 'span.name'
comment.find(selector).text
rescue Capybara::ElementNotFound => e
Rails.logger.warn('Could not get author_name: ' + e)
puts e
''
end
When i run this code and successfully rescue a Capybara::ElementNotFound error it blows up with the following error:
TypeError: no implicit conversion of Capybara::ElementNotFound into String
The strange thing is that the puts e line will print out the error no problem.
My question is this:
Why would the concatenation attempt cause problems printing e when i can successfully print out e with puts? Don't both of them result in a .to_s call under the covers?
Ruby actually uses the implicit #to_str method when concatenating strings, rather than #to_s.
In this case, the simplest solution is probably to change your code to:
Rails.logger.warn('Could not get author_name: ' + e.to_s)
If you want to avoid that for some reason, and would rather have all error objects behave as you expected when doing string concatenation in the future, you could also open up the StandardError class and define to_str:
class StandardError
def to_str
self.to_s
end
end

ruby raise exception on iterator

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.

Suppress an error when saving a record in Rails

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

How do I get the entire error stack when raising an exception?

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.

Outputting errors in a rescue (Ruby/Rails)

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

Resources