Ruby on Rails中如何遍历对象数组创建OrderDetail类新实例?
Rails订单与订单详情关联创建问题处理
问题描述
我有一个Order模型,其中包含名为item_details的对象数组。创建新订单时,需要遍历item_details数组,创建对应Order ID的OrderDetail实例。由于OrderDetail是关联表,必须在Order创建完成后才能生成实例,这样才能把order_id写入OrderDetails。目前我已经把item_details的数据类型设为json来实现数据库存储;之前用text/string类型时,会出现符号被保存为字符串的问题。
订单示例
{ "id": 5, "customer_id": 1, "order_date": "2023-01-03", "total_cost": 0, "item_details": [ { "product_id": 3, "quantity": 3 }, { "product_id": 9, "quantity": 4 } ] }
数据库Schema
create_table "order_details", force: :cascade do |t| t.integer "product_id" t.integer "order_id" t.integer "quantity" t.datetime "created_at", precision: 6, null: false t.datetime "updated_at", precision: 6, null: false end create_table "orders", force: :cascade do |t| t.integer "customer_id" t.string "order_date" t.datetime "created_at", precision: 6, null: false t.datetime "updated_at", precision: 6, null: false t.json "item_details" end
模型代码
Order模型
class Order < ApplicationRecord belongs_to :customer has_many :order_details has_many :products, through: :order_details end
OrderDetail模型
class OrderDetail < ApplicationRecord validates :quantity, numericality: { only_integer: true } belongs_to :order belongs_to :product end
序列化器代码
OrderSerializer
class OrderSerializer < ActiveModel::Serializer attributes :id, :customer_id, :order_date, :total_cost, :item_details belongs_to :customer has_many :order_details has_many :products def total_cost cost = [] self.object.order_details.each do |details| product = self.object.products.find {|product| product.id == details.product_id} cost << product.price * details.quantity end return cost.sum end end
OrderDetailSerializer
class OrderDetailSerializer < ActiveModel::Serializer attributes :id, :product_id, :order_id, :quantity, :product belongs_to :order belongs_to :product end
控制器代码
Orders控制器
class OrdersController < ApplicationController wrap_parameters format: [] skip_before_action :authorized, only: :create def index orders = Order.all if orders render json: orders else render json: {error: "未找到订单" }, status: :not_found end end def show order = Order.find_by(id: params[:id]) if order render json: order else render json: { error: "未找到订单" }, status: :not_found end end def create order = Order.create(order_params) if order.valid? order.item_details.each do |i| OrderDetail.create(order_id: params[:id], product_id: i[:product_id], quantity: i[:quantity]) end render json: order else render json: { errors: order.errors.full_messages }, status: :unprocessable_entity end end def update order = Order.find_by(id: params[:id]) if order order.update(order_params) render json: order else render json: { error: "未找到订单" }, status: :not_found end end def destroy order = Order.find_by(id: params[:id]) if order order.destroy head :no_content else render json: {error: "未找到订单"}, status: :not_found end end private def order_params params.permit(:customer_id, :order_date, item_details: [:product_id, :quantity] ) end end
OrderDetails控制器
class OrderDetailsController < ApplicationController skip_before_action :authorized, only: :create def index order_details = OrderDetail.all if order_details render json: order_details else render json: {error: "未找到记录"}, status: :not_found end end def create order_detail = OrderDetail.create(order_details_params) if order_detail.valid? render json: order_detail else render json: { errors: order_detail.errors.full_messages }, status: :unprocessable_entity end end def update order_detail = OrderDetail.find_by(id: params[:id]) if order_detail order_detail.update(order_details_params) render json: order_detail else render json: { error: "未找到记录" }, status: :not_found end end private def order_details_params params.permit(:order_id, :product_id, :quantity) end end
关键问题修正提示
注意到OrdersController的create方法中,创建OrderDetail时使用了params[:id],这是错误的——刚创建的order实例的ID应该用order.id,params[:id]此时还不存在。修正后的create方法如下:
def create order = Order.create(order_params) if order.valid? order.item_details.each do |i| OrderDetail.create(order_id: order.id, product_id: i[:product_id], quantity: i[:quantity]) end render json: order else render json: { errors: order.errors.full_messages }, status: :unprocessable_entity end end
另外,既然已经通过OrderDetail关联订单和商品,Order模型中的item_details字段其实可以不需要存储,因为关联数据已经保存在order_details表中,避免数据冗余。可以考虑移除orders表中的item_details字段,直接从请求参数中获取商品详情来创建OrderDetail实例。
内容的提问来源于stack exchange,提问作者angiem103
相关产品推荐
相关产品推荐

