我有一个 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"}]
然后,我想在我的数据库中查询items
记录,其中id
值与请求参数中的item_id
数字匹配。我正在这样做:
items = Item.where(id: purchase_list.pluck(:item_id))
然后,当我尝试以任何方式使用items
时,例如只是这样的东西(为简洁起见,省略了实际功能):
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()
,试图让它以其他方式工作,但我无法让它工作。它总是给出ActiveRecord::UnknownAttributeReference
错误。
我也尝试过用to_i
将它们转换为数字,但这无济于事。
但是从我在 Rails 指南和其他地方读到的内容来看,如果我使用像这样的"哈希条件"来调用where
where(id: [x,y,z])
,这是指定 Rails 应该自动清理输入以防止 MySQL 注入之类的where
条件的方法之一?我以为只有用"纯字符串"来称呼where
才会让它变得脆弱?
如果有人能向我解释,我将不胜感激:
- 如果我使用的方法,为什么 Rails 会给我这个错误,而 Rails 应该清理输入以使其安全?
- 我怎样才能完成我想做的事情?用
Arel.sql()
或任何其他方式?
我正在使用的版本:
ruby "3.0.3"
gem "rails", "~> 7.0.3", ">= 7.0.3.1"
一定有一些你没有在这里展示的东西。我在本地尝试了该代码,它对我有用。
你能尝试在Rails控制台中运行这段代码吗?
pry(main)> params = ActionController::Parameters.new({"list"=>[{"item_id"=>"417", "quantity"=>"5"}, {"item_id"=>"418", "quantity"=>"1"}, {"item_id"=>"416", "quantity"=>"2"}], "controller"=>"items", "action"=>"total"})
=> #<ActionController::Parameters {"list"=>[{"item_id"=>"417", "quantity"=>"5"}, {"item_id"=>"418", "quantity"=>"1"}, {"item_id"=>"416", "quantity"=>"2"}], "controller"=>"items", "action"=>"total"} permitted: false>
pry(main)> purchase_list = params.permit(list: [:item_id, :quantity])[:list]
=> [#<ActionController::Parameters {"item_id"=>"417", "quantity"=>"5"} permitted: true>,
#<ActionController::Parameters {"item_id"=>"418", "quantity"=>"1"} permitted: true>,
#<ActionController::Parameters {"item_id"=>"416", "quantity"=>"2"} permitted: true>]
pry(main)> ids = purchase_list.pluck(:item_id)
=> ["417", "418", "416"]
pry(main)> Item.where(id: ids)