Question

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
Was it helpful?

Solution

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

OTHER TIPS

You can change a parameter to int:

params[:id] = params[:id].to_i if params[:id].present?
things= @member.things.where("id>?",params[:id])

Or you can add validator for params in config/routes.rb:

resources :things, :constraints => {:id => /\d+/}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top