与rails API的HABTM关系不起作用
我是Ruby on Rails中的新成员。我正在使用Rails 5.1,活动记录序列化器,门卫和设计宝石制作Rails API。与rails API的HABTM关系不起作用
我有一个Order
表,它有许多产品。订单和产品之间的关系是多对多的。
订货型号:
class Order < ApplicationRecord
validates_presence_of :brute, :net
has_and_belongs_to_many :products
end
产品型号:
class Product < ApplicationRecord
belongs_to :category
validates_presence_of :name, :price
validates_uniqueness_of :name
has_and_belongs_to_many :orders
end
我有一个名为orders_products
连接表。
订购串行:
class OrderSerializer < ActiveModel::Serializer
attributes :id, :discount, :brute, :net, :payed, :payed_at, :products
def products
object.products.map do |product|
ProductSerializer.new(product, scope: scope, root: false, event: object)
end
end
end
产品序列化:
class ProductSerializer < ActiveModel::Serializer
attributes :id, :name, :price, :description
has_one :category
end
令控制器:
module Api
class OrdersController < ApiController
before_action :set_order, only: [:show, :update, :destroy]
# GET /api/orders
def index
@orders = Order.all
render json: @orders
end
# GET /api/orders/1
def show
render json: @order
end
# POST /api/orders
def create
@order = Order.new(order_params)
if @order.save
render json: @order, status: :created, location: api_order_url(@order)
else
render json: @order.errors, status: :unprocessable_entity
end
end
# PATCH/PUT /api/orders/1
def update
if @order.present?
if @order.update(order_params)
render json: @order
else
render json: @order.errors, status: :unprocessable_entity
end
end
end
# DELETE /api/orders/1
def destroy
@order.destroy if @order.present?
end
private
# Use callbacks to share common setup or constraints between actions.
def set_order
@order = Order.find(params[:id])
rescue ActiveRecord::RecordNotFound
Rails.logger.error{ 'Order record is not found' }
nil
end
# Only allow a trusted parameter "white list" through.
def order_params
params.require(:order).permit(:discount, :brute, :net, :payed, :payed_at, product_ids: [])
end
end
end
当我发布的API生成器应用中的一些秩序JSON数据,如邮差/失眠,订单正在保存在订单表中,但没有保存在orders_products
连接表中的数据。
我的订单JSON的请求(POST http://localhost:3000/api/orders):
{
"discount": 110,
"brute": 100,
"net": 200,
"payed": null,
"payed_at": null,
"product_ids": [3]
}
我试图找到解决办法,但我失败了。
最后,我在你的problem.Just已经解决了在模型中添加属性。
订货型号:
class Order < ApplicationRecord
attribute :product_ids
validates_presence_of :brute, :net
has_and_belongs_to_many :products
end
订购串行:
class OrderSerializer < ActiveModel::Serializer
attributes :id, :discount, :brute, :net, :payed, :payed_at
has_many :products
end
而且在您的订单API创建方法:
# POST /api/orders
def create
@order = Order.new(order_params)
if @order.save
# Find products
@products = Product.where(id: order_params[:product_ids])
# Create join table records
@products.each { |product| product.orders << @order }
render json: @order, status: :created, location: api_order_url(@order)
else
render json: @order.errors, status: :unprocessable_entity
end
end
我在本地已经测试和它的作品!快乐编程:)
谢谢@Engr。坦比尔哈桑,你应该得到一枚奖牌。 –
据我所知,当给定一个id列表时,Rails不会自动处理创建连接记录。因此,当你打电话给@order = Order.new(order_params)
并期待它知道如何处理product_ids: [3]
时,它只是忽略它。
如果您使用以下方式修改您的create
端点,则应该看到正在创建的连接记录。
# POST /api/orders
def create
@order = Order.new(order_params)
if @order.save
# Find products
@products = Product.where(id: order_params[:product_ids])
# Create join table records
@products.each { |product| product.orders << order }
render json: @order, status: :created, location: api_order_url(@order)
else
render json: @order.errors, status: :unprocessable_entity
end
end
这只是一个可能的解决方案,不会做任何错误检查。根据您的应用程序的安全性和健壮性,您可能需要创建一个服务来包装此应用程序,并在创建订单和关联记录之前处理验证产品。
编辑:OrderSerializer
一旦你验证正在正确创建的连接表中的记录。检查你的序列化程序是否正常工作,他们有很好的文档。我相信你可以在OrderSerializer
这个换出当前的products
方法:
class OrderSerializer < ActiveModel::Serializer
attributes :id, :discount, :brute, :net, :payed, :payed_at, :products
def products
object.products.map do |product|
ProductSerializer.new(product).serializable_hash
end
end
end
order_params [:product_ids]当我从json API请求时返回nil。为什么? –
这听起来像是你有两个问题。第一个问题是连接表记录没有被创建。我上面介绍的解决方案应该解决这个问题,您是否证实现在正在创建记录?如果他们是和你的JSON输出仍然不正确,那么你的序列化器是错误的。添加上面的信息。 – Genzume
您提供的方法是正确的,我检查了它@products = Product.where(id:3),然后连接表正在创建。但是当我调试并发现order_params [:product_ids]总是返回nil并且order_params不包含任何product_ids!我的json格式不正确? 你的'serializable_hash'返回错误,它需要两个缺失的参数。 –
我不使用序列化程序,所以我不太熟悉你的一些代码。虽然您可以指出您的代码中的哪个位置可以将产品添加到您的订单中吗?也许你可以复制视图(erb)文件,在这里处理太多.. – Maxence
我也面临同样的问题。但是在使用活动记录序列化程序gem时没有erb文件。 –