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
相关产品推荐
相关产品推荐

