2017-10-09 76 views
2

我是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] 
} 

我試圖找到解決辦法,但我失敗了。

+0

我不使用序列化程序,所以我不太熟悉你的一些代碼。雖然您可以指出您的代碼中的哪個位置可以將產品添加到您的訂單中嗎?也許你可以複製視圖(erb)文件,在這裏處理太多.. – Maxence

+0

我也面臨同樣的問題。但是在使用活動記錄序列化程序gem時沒有erb文件。 –

回答

1

最後,我在你的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 

我在本地已經測試和它的作品!快樂編程:)

+0

謝謝@Engr。坦比爾哈桑,你應該得到一枚獎牌。 –

0

據我所知,當給定一個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 
+0

order_params [:product_ids]當我從json API請求時返回nil。爲什麼? –

+0

這聽起來像是你有兩個問題。第一個問題是連接表記錄沒有被創建。我上面介紹的解決方案應該解決這個問題,您是否證實現在正在創建記錄?如果他們是和你的JSON輸出仍然不正確,那麼你的序列化器是錯誤的。添加上面的信息。 – Genzume

+0

您提供的方法是正確的,我檢查了它@products = Product.where(id:3),然後連接表正在創建。但是當我調試並發現order_params [:product_ids]總是返回nil並且order_params不包含任何product_ids!我的json格式不正確? 你的'serializable_hash'返回錯誤,它需要兩個缺失的參數。 –