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

Ruby on Rails中如何将对象数组存入Order表的item_details字段

问题

我有一个Order表,其中包含item_details字段,希望该字段的值为对象数组。目前请求能成功提交,但返回的item_details是类似"{\"product_id\"=>1, \"quantity\"=>2}"的字符串而非实际对象,请问该如何修复?

相关代码及请求、返回结果:

Order Controller

class OrdersController < ApplicationController

    skip_before_action :authorized, only: :create

    def index
        orders = Order.all
        if orders
        render json: orders
        else
            render json: {error: "Order Not Found" }, status: :not_found
        end
    end

    def show
        order = Order.find_by(id: params[:id])
        if order
            render json: order
        else
            render json: { error: "Order Not Found" }, status: :not_found
        end
    end

    def create
        order = Order.create(order_params)
        render json: order, status: :created
    end

    def update
        order = Order.find_by(id: params[:id])
        if order
            order.update(order_params)
            render json: order
        else
            render json: { error: "Order Not Found" }, status: :not_found
        end
    end


    private

    def order_params
        params.permit(:customer_id, :order_date,{ item_details: [:product_id, :quantity] })
    end

end

Order Serializer

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

Schema

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.text "item_details", default: [], array: true
  end

Postman请求

{
    "customer_id": 1,
    "order_date": 1,
    "item_details": [
        {
            "product_id": 1,
            "quantity" : 2
        },
        {
            "product_id": 7,
            "quantity" : 1
        }
    ]
}

Postman返回结果

{
    "id": 2,
    "customer_id": 1,
    "order_date": "1",
    "total_cost": 0,
    "item_details": [
        "{\"product_id\"=>1, \"quantity\"=>2}",
        "{\"product_id\"=>7, \"quantity\"=>1}"
    ],
    "customer": {
        "id": 1,
        "name": "John Smith",
        "phone_number": "(811) 833 2172",
        "email": "john@yahoo.com",
        "address": "334 Jacobs Plaza, West Robtport, IN 26209-0933",
        "username": "john103",
        "password": null
    },
    "order_details": [],
    "products": []
}

不清楚为什么哈希会以这种字符串形式呈现,而非实际对象?

解决方案

1. 修改数据库字段类型为JSONB数组

当前Schema中item_details是text类型数组,Rails无法识别哈希结构,只能将其转为Ruby字符串格式存储。需要改成JSONB类型数组,让数据库原生支持JSON对象/数组的存储与解析:

生成迁移文件:

rails generate migration ChangeItemDetailsToJsonbArrayInOrders

编辑迁移文件内容:

class ChangeItemDetailsToJsonbArrayInOrders < ActiveRecord::Migration[7.0]
  def change
    remove_column :orders, :item_details
    add_column :orders, :item_details, :jsonb, default: [], array: true
  end
end

执行迁移:

rails db:migrate

2. 配置模型序列化(可选)

在app/models/order.rb中添加序列化配置,确保Rails自动处理哈希与JSON的转换:

class Order < ApplicationRecord
  serialize :item_details, JSON
end

3. 验证修复效果

重新提交Postman请求,此时返回的item_details会是正常的对象数组:

{
    "id": 3,
    "customer_id": 1,
    "order_date": "1",
    "total_cost": 0,
    "item_details": [
        {"product_id": 1, "quantity": 2},
        {"product_id": 7, "quantity": 1}
    ],
    // ...其他字段
}

原因说明

  • text数组类型仅能存储字符串,Rails会把传入的哈希直接转为Ruby哈希的字符串表示(即inspect方法的输出格式)。
  • JSONB是PostgreSQL原生支持的JSON类型,可直接存储JSON结构,Rails会自动完成哈希与JSON格式的双向转换,无需手动处理字符串解析。

内容的提问来源于stack exchange,提问作者angiem103

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 04:45:55