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

Rails同表单批量更新多条记录报错及值覆盖问题排查

Rails批量更新多条记录的问题解决

第一个写法的错误

index_by(&:id)返回的哈希中,值是Previtem对象而非属性哈希。你循环时把对象传给update方法,自然触发「必须传哈希」的错误。

修正思路:直接构造要更新的属性哈希,而非从数据库对象提取。示例:

def marcado 
  set_previsao
  @previsao.previtems.where(status: "Confirmado").each do |item|
    item.update(status: "Marcado", data_marcacao: 对应日期值)
  end
end

第二个写法的错误

你给所有记录都赋值同一个params[:data_marcacao],结果自然全是同一个值。要实现每条记录对应不同日期,必须让表单参数按记录id区分:

表单设置(ERB示例)

<% @previsao.previtems.where(status: "Confirmado").each do |item| %>
  <%= text_field_tag "previtems[#{item.id}][data_marcacao]", item.data_marcacao %>
<% end %>

控制器方法修正

def marcado 
  set_previsao
  target_ids = @previsao.previtems.where(status: "Confirmado").pluck(:id)
  # 只处理目标记录,合并强制更新的status字段
  params[:previtems].slice(*target_ids).each do |id, attrs|
    @previsao.previtems.find(id).update(attrs.merge(status: "Marcado"))
  end
end

性能优化:批量SQL更新

循环调用update会触发多次SQL查询,用upsert_all可以一次完成批量更新,大幅提升性能:

def marcado 
  set_previsao
  target_items = @previsao.previtems.where(status: "Confirmado")
  update_data = target_items.map do |item|
    { id: item.id, status: "Marcado", data_marcacao: params[:previtems][item.id.to_s][:data_marcacao] }
  end
  Previtem.upsert_all(update_data, unique_by: :id)
end

内容的提问来源于stack exchange,提问作者Cesar De Paula Souza

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 18:12:22