Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why ActiveRecord::StatementInvalid cannot be rescued in this Rails method?

Why I cannot rescue anything in the following method?

def get_things
  begin
    things= @member.things.where("id>?",params[:id])
  rescue ActiveRecord::StatementInvalid
    render( inline: "RESCUED ActiveRecord::StatementInvalid" )
    return
  rescue
    render( inline: "RESCUED something" )
    return
  end
  render( inline: "#{things.first.title}" )
end

When called with a valid id, it works:

$  curl -vd "id=3" http://localhost:3000/get_things

but if I pass a wrong one, such as:

$  curl -vd "id=3,0" http://localhost:3000/get_things
$  curl -vd "id='3'" http://localhost:3000/get_things

the exception isn't rescued:

< HTTP/1.1 500 Internal Server Error
<h1>
  ActiveRecord::StatementInvalid
    in ApplicationController#get_things
</h1>
<pre>PG::Error: ERROR:  invalid input syntax for integer: &quot;'3'&quot;

Only when rendering happens inside begin/rescue block

def get_things
  begin
    things= @member.things.where("id>?",params[:id])
    render( inline: "#{things.first.title}" )
  rescue ActiveRecord::StatementInvalid
    render( inline: "RESCUED ActiveRecord::StatementInvalid" )
    return
  end
end

it works as expected:

$ curl -vd "id='3'" http://localhost:3000/get_things
  < HTTP/1.1 200 OK
  RESCUED ActiveRecord::StatementInvalid
like image 259
Claudio Floreani Avatar asked Feb 20 '23 20:02

Claudio Floreani


1 Answers

As far as I know, the things in your case will be a class containg information on your query, but the query won't be executed till you try to acces an element based on the query (like things.first).

things= @member.things.where("id>?",params[:id]) # query not run
things= things.order("id desc") # still not run
things.first.title # now the query runs, the statement can be invalid

This is why it can't be rescued, because in your render line, where the exception occurs, not in the creation of the things.

This should be okay:

def get_things
  begin
    things= @member.things.where("id>?",params[:id])
    thing_title = things.first.title
  rescue ActiveRecord::StatementInvalid
    render( inline: "RESCUED ActiveRecord::StatementInvalid" )
    return
  rescue
    render( inline: "RESCUED something" )
    return
  end
  render( inline: "#{thing_title}" )
end
like image 125
Matzi Avatar answered May 08 '23 09:05

Matzi