You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rails7升级后sanitize_sql_array将数值转为字符串,求解决方法

Rails 7升级后sanitize_sql_array数值被转字符串的解决方法

问题描述

将Rails从6.1升级到7后,调用ActiveRecord::Base.send(:sanitize_sql_array)时,传入的整数、浮点数会被自动转为带引号的字符串,导致SQL语句中的数值运算逻辑异常。

示例代码

输入参数:

updates = ["`bed_count` = `bed_count` + ?", "`operating_room_count` = `operating_room_count` + ?", "`updated_at` = ?"]
values = [3.14159, 1, "2022-09-17 18:15:05"]

Rails 7执行结果(数值被加引号):

>> ActiveRecord::Base.send(:sanitize_sql_array, [updates.join(','), *values])
=> "`bed_count` = `bed_count` + '3.14159',`operating_room_count` = `operating_room_count` + '1',`updated_at` = '2022-09-17 18:33:44'"

Rails 6.1执行结果(数值保持原样):

"`bed_count` = `bed_count` + 3.14159,`operating_room_count` = `operating_room_count` + 1,`updated_at` = '2022-09-17 18:33:44'"

解决方案

1. 使用sanitize_sql_for_assignment替代

该方法专门用于处理更新语句的赋值逻辑,能正确识别并保留数值类型:

ActiveRecord::Base.send(:sanitize_sql_for_assignment, updates.zip(values).to_h)

执行后会生成正确的SQL片段,数值不会被添加引号。

2. 逐个处理占位符后拼接

循环处理每个更新语句与对应的值,分别调用sanitize后再拼接:

sanitized_updates = updates.zip(values).map do |sql, val|
  ActiveRecord::Base.send(:sanitize_sql_array, [sql, val])
end.join(',')

这种方式确保每个占位符都被单独正确处理,数值类型得以保留。

3. 使用Arel构建更新语句(推荐)

避免手动拼接SQL,用Arel生成安全的更新逻辑,完全无需手动处理sanitize,同时遵循Rails最佳实践:

table = YourModel.arel_table
update_manager = Arel::UpdateManager.new(Arel::Table.engine)
update_manager.table(table)
update_manager.set([
  table[:bed_count].eq(table[:bed_count] + 3.14159),
  table[:operating_room_count].eq(table[:operating_room_count] + 1),
  table[:updated_at].eq('2022-09-17 18:15:05')
])
puts update_manager.to_sql

此方法不仅解决数值转字符串问题,还能有效避免SQL注入风险。

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 20:10:44