我正在使用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
答案 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。