将日期参数传递给rails中的sql select查询(QueryMethods)

时间:2017-11-29 03:46:32

标签: ruby-on-rails postgresql ruby-on-rails-4 psql

我正在使用brakeman gem(它识别Ruby on Rails代码中可能存在的安全问题)。我们有一个使用连接,组和选择的范围,我需要更新查询的选择部分。此范围如下所示。我将范围内容放在产品型号上。

Product.joins('LEFT JOIN orders ON orders.product_id = products.id')
  .group('products.id')
  .select(
    "SUM(CASE WHEN orders.order_at BETWEEN '#{start_date}' AND '#{end_date}'" \
    " THEN orders.qty ELSE 0 END) as qty, products.*"
  )

现在如果我尝试像这样更改查询

Product.joins('LEFT JOIN orders ON orders.product_id = products.id')
  .group('products.id')
  .select(
    "SUM(CASE WHEN orders.order_at BETWEEN ? AND ?" \
    " THEN orders.qty ELSE 0 END) as qty, products.*",
    '#{start_date}',
    '#{end_date}'
  )

它给了我语法错误,我有?我也尝试了其他一些方法,但是它并没有为我工作。我正在使用带有rails 4.1.8的postgres sql 他们以任何方式实现这一目标吗?提前谢谢。

这是错误

  

PG :: SyntaxError:ERROR:语法错误在或附近"?"
    第1行:选择   SUM(例如,订单。订单,订单等等?和?和ord

1 个答案:

答案 0 :(得分:0)

您使用?语法是正确的,但是您对select的调用需要将其中的一部分拆分为对where intead的调用。

此外,您将日期转换为字符串(例如'#{start_date}')。这可以防止被调用的方法将值作为日期处理和格式化。相反,只需传递原始日期(例如start_date)。

Product
  .joins('LEFT JOIN orders ON orders.product_id = products.id')
  .where('orders.order_at BETWEEN ? AND ?', start_date, end_date)
  .select("SUM(orders.qty) as qty, products.*")
  .group('products.id')

您还可以根据daino3的回答(where)重做.where(orders: {order_at: start_date..end_date})来电。

推理

不在where(或相关)调用中直接嵌入参数至关重要。这样做可以将您的代码打开到主要的安全风险,称为SQL Injection,因为远程用户可能会放置任意数据串,触发对您的数据库执行各种危险调用。

这就是为什么你应该总是where('various sql things ?', parameter)而不是where("various sql things #{parameter}")

有关向Rails sql调用传递参数的更多信息,请查看official Rails Guide on the Active Record Query Interface