You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Sinatra+ActiveRecord+PG数据库查询错误处理方案咨询

捕获ActiveRecord查询异常并返回友好提示

嘿,我来帮你搞定这个问题!你的现有代码直接拼接请求参数到SQL语句里,不仅容易触发数据库异常,还存在SQL注入风险,咱们可以通过「参数预验证+异常捕获」两步来实现需求,同时让代码更安全。

完整解决方案代码

get '/cars' do
  # 先定义Car模型允许的查询属性和排序方向,从根源避免无效参数和SQL注入
  allowed_attributes = Car.attribute_names
  allowed_orders = ['asc', 'desc']

  # 处理属性参数:默认用id排序,无效属性直接返回提示
  attribute = params[:attribute] || 'id'
  unless allowed_attributes.include?(attribute)
    status 400
    return { error: "Sorry, but there is no attribute with name #{attribute}" }.to_json
  end

  # 处理排序方向:默认升序,无效方向强制转成asc
  order_dir = params[:order] || 'asc'
  order_dir = 'asc' unless allowed_orders.include?(order_dir.downcase)

  # 处理分页参数:确保是整数,避免非数值导致的错误
  limit = params[:limit] ? params[:limit].to_i : 20
  offset = params[:offset] ? params[:offset].to_i : 0

  begin
    # 执行查询并返回JSON
    @cars = Car.order("#{attribute} #{order_dir}").limit(limit).offset(offset)
    @cars.to_json
  rescue ActiveRecord::StatementInvalid => e
    # 捕获数据库语句错误,返回友好提示
    status 400
    { error: "Invalid query: #{e.message.split(':').last.strip}" }.to_json
  end
end

关键细节说明

  • 参数预验证更高效:提前用Car.attribute_names检查传入的attribute是否是模型的合法字段,比等数据库报错再处理更高效,还能彻底避免SQL注入(毕竟只有合法字段才会被拼进SQL)。
  • 安全处理所有参数:排序方向限制为asc/desc,分页参数转成整数,避免非预期的参数类型触发错误。
  • 精准捕获异常:用begin-rescue包裹查询逻辑,捕获ActiveRecord::StatementInvalid——这是ActiveRecord包装数据库底层错误的标准异常类,能覆盖大部分SQL语法错误、字段不存在等场景。
  • 正确返回HTTP状态码:用400(Bad Request)告诉客户端“你的请求参数有问题”,而不是默认的200或500,更符合REST规范。

进阶:精准识别PG特定错误

如果你需要更细粒度的错误处理(比如只针对“字段不存在”的情况返回特定提示),可以从异常中提取PostgreSQL的原始错误:

rescue ActiveRecord::StatementInvalid => e
  pg_error = e.original_exception
  if pg_error.is_a?(PG::UndefinedColumn)
    status 400
    { error: "Sorry, but there is no attribute with name #{params[:attribute]}" }.to_json
  else
    # 其他数据库错误返回通用提示
    status 500
    { error: "Database error occurred: #{pg_error.message}" }.to_json
  end
end

这样就能精准识别PG的「UndefinedColumn」错误,返回你想要的专属提示,其他数据库错误则返回通用信息。

内容的提问来源于stack exchange,提问作者Julia

火山引擎 最新活动