Rails 7中订单更新时如何保存原状态至OrderHistory模型
解决方案
1. 先创建OrderHistory模型
首先生成模型和对应的数据库迁移:
rails generate model OrderHistory order:references order_history:json rails db:migrate
这会自动创建包含order_id(关联Order模型)和order_history(JSON类型字段)的数据表,同时在Order模型中建立一对多关联。
2. 保存订单更新前的快照
有两种常用实现方式,推荐优先用模型回调(更贴合Rails的MVC设计原则):
方式一:模型层回调(推荐)
修改app/models/order.rb,添加before_update回调,在订单更新前自动保存历史状态:
class Order < ApplicationRecord has_many :order_histories, dependent: :destroy before_update :save_order_history private def save_order_history # 排除系统自动维护的时间字段,保存订单当前的完整属性快照 order_histories.create(order_history: attributes.except('created_at', 'updated_at')) end end
这样每次订单更新时,都会自动把更新前的状态存入OrderHistory表,不需要修改控制器代码。
方式二:控制器中显式处理
如果更倾向在控制器里手动控制逻辑,修改app/controllers/orders_controller.rb的update方法:
def update # 提前获取更新前的订单状态,这个变量仅当前请求上下文有效 original_order_state = @order.attributes.except('created_at', 'updated_at') respond_to do |format| if @order.update(order_params) # 保存历史记录 OrderHistory.create(order_id: @order.id, order_history: original_order_state) format.html { redirect_to order_url(@order), notice: "Order was successfully updated." } format.json { render :show, status: :ok, location: @order } else format.html { render :edit, status: :unprocessable_entity } format.json { render json: @order.errors, status: :unprocessable_entity } end end end
关于变量跨用户可见的问题
你完全不用顾虑控制器里的变量会被其他用户访问到——Rails每个HTTP请求都会创建一个全新的控制器实例,请求处理完成后这个实例就会被销毁。比如你定义的original_order_state或者控制器里的@order,都只属于当前请求的独立上下文,其他用户的请求会拥有自己专属的控制器实例和变量,互相完全隔离。
内容的提问来源于stack exchange,提问作者EastsideDev
相关产品推荐
相关产品推荐

