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

如何在Rails调用where时避免ActiveRecord::UnknownAttributeReference错误?

Rails查询时ActiveRecord::UnknownAttributeReference错误排查

问题场景

我有一个Rails应用,接口接收的参数结构如下:

=> #<ActionController::Parameters {"list"=>[{"item_id"=>"417", "quantity"=>"5"}, {"item_id"=>"418", "quantity"=>"1"}, {"item_id"=>"416", "quantity"=>"2"}], "controller"=>"items", "action"=>"total"} permitted: false>

通过require和permit处理参数的方法:

def purchase_list
  params.require(:list).map do |list_entry|
    list_entry.permit(:item_id, :quantity).to_h
  end
end

调用该方法得到purchase_list变量:

[{"item_id"=>"417", "quantity"=>"5"}, {"item_id"=>"418", "quantity"=>"1"}, {"item_id"=>"416", "quantity"=>"2"}]

我通过以下代码查询与请求中item_id匹配的Item记录:

items = Item.where(id: purchase_list.pluck(:item_id))

但执行以下代码时出现错误:

x = Item.first.id
items.pluck(id: x)

错误信息:

ActiveRecord::UnknownAttributeReference:
  Dangerous query method (method whose arguments are used as raw SQL) called with non-attribute argument(s): {:id=>425}.This method should not be called with user-provided values, such as request parameters or model attributes. Known-safe values can be passed by wrapping them in Arel.sql().

我尝试用Arel.sql()解决但未成功,转成数字也无效。根据Rails文档,使用哈希条件的where(id: [x,y,z])应该会自动过滤输入,只有纯字符串的where才会有风险?

我想请教:

  1. 为何使用安全写法仍出现该错误?
  2. 如何通过Arel.sql()或其他方式解决问题?

使用版本:

ruby "3.0.3"
gem "rails", "~> 7.0.3", ">= 7.0.3.1"

解答

1. 错误原因

错误并非来自where(id: purchase_list.pluck(:item_id))——这行的哈希写法确实是安全的,Rails会自动处理参数过滤。问题出在items.pluck(id: x)这行代码:

  • pluck方法的设计是接收属性名(符号或字符串),用来批量获取指定字段的值,比如items.pluck(:id)会返回所有匹配记录的id数组。
  • 当你传入哈希{id: x}时,Rails无法识别这是合法的属性名,会将其视为需要直接拼接的SQL片段,触发安全检测机制,因此抛出UnknownAttributeReference错误。

2. 解决方法

根据你的需求,有几种更合理的实现方式:

方式一:先筛选再取值(推荐)

如果你需要从items集合中获取id等于x的记录的id,应该先通过where筛选,再用pluck:

items.where(id: x).pluck(:id)
# 如果只需要单个值,更高效的写法是:
items.find_by(id: x)&.id

方式二:用Arel处理(不推荐,仅作演示)

如果你一定要用pluck配合自定义SQL逻辑(实际场景中没必要这么做),可以用Arel.sql()包裹合法的SQL片段:

items.pluck(Arel.sql("CASE WHEN id = #{x} THEN id END"))

这种写法会返回所有记录的结果:匹配的记录返回id,不匹配的返回nil,显然不如方式一高效。


内容的提问来源于stack exchange,提问作者C. Ball

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.23 05:03:19