Rails 5.2升级后模型Scope触发危险SQL查询方法弃用警告求助
解决Rails 5.2中Scope的弃用警告问题
这个警告是Rails为了推进更安全的查询写法给我们的提前预警——到了Rails 6.0,直接在查询方法里传递非属性的原始SQL参数会被彻底禁止。你原来的写法虽然用了sanitize_sql_array,但order方法接收的是处理后的SQL字符串,还是会被检测为“非安全的原始SQL参数”。
下面给你一个完全合规、兼容Rails 5.2+的解决方案,用Rails底层的Arel查询构造器实现,既安全又不会触发警告:
scope :indexed_by_array, lambda { |ids| return none if ids.empty? # 获取当前模型id字段的Arel节点 id_column = arel_table[:id] # 构造用于匹配的目标字符串,格式为",id1,id2,id3," target_string = ids.join(',').prepend(',').concat(',') # 用Arel构建POSITION函数的SQL表达式 position_expr = Arel::Nodes::NamedFunction.new( 'POSITION', [ # 构造 ',' || id::text || ',' 的Arel表达式 Arel::Nodes::InfixOperation.new( '||', Arel::Nodes.build_quoted(','), Arel::Nodes::InfixOperation.new('||', id_column.cast_to_text, Arel::Nodes.build_quoted(',')) ), Arel::Nodes.build_quoted(target_string) ] ) where(id: ids).order(position_expr.asc) }
为什么这个写法有效?
- Arel是Rails内置的查询构造器,所有生成的SQL都会经过Rails的安全校验,完全符合Rails 5.2和6.0的规范,不会触发弃用警告。
- 我们没有直接拼接SQL字符串,而是通过Arel的节点方法构建表达式,从根源上避免了SQL注入风险。
- 完整保留了原功能:按照传入的
ids数组顺序返回查询结果。
额外优化点
- 增加了
ids.empty?的判断,直接返回none(空关系),避免生成无效的SQL语句。
内容的提问来源于stack exchange,提问作者t56k
相关产品推荐
相关产品推荐

