【问题标题】:Why ActiveRecord::StatementInvalid cannot be rescued in this Rails method?为什么 ActiveRecord::StatementInvalid 不能在这个 Rails 方法中被拯救?
【发布时间】:2012-07-14 13:01:16
【问题描述】:

为什么我无法通过以下方法拯救任何东西?

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

当使用有效 id 调用时,它可以工作:

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

但是如果我传错了,比如:

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

异常未获救:

< 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;

仅当渲染发生在开始/救援块内时

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

它按预期工作:

$ curl -vd "id='3'" http://localhost:3000/get_things
  < HTTP/1.1 200 OK
  RESCUED ActiveRecord::StatementInvalid

【问题讨论】:

    标签: ruby-on-rails exception activerecord rescue


    【解决方案1】:

    据我所知,在您的情况下,things 将是一个包含查询信息的类,但是在您尝试访问基于查询的元素之前,查询不会被执行(例如 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
    

    这就是它无法挽救的原因,因为在发生异常的渲染行中,而不是在 things 的创建中。

    这应该没问题:

    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
    

    【讨论】:

    • 谢谢,这很有趣。
    【解决方案2】:

    您可以将参数更改为int:

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

    或者您可以在config/routes.rb 中添加参数验证器:

    resources :things, :constraints => {:id => /\d+/}
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-06-21
      • 1970-01-01
      • 2013-10-31
      • 2013-09-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多