简体   繁体   English

使用has_many:through关系为现有子级创建新的父级记录

[英]Create new parent record with has_many :through relationship for existing children

I am working on a Ruby on Rails API (version 4.0) to create and update invoices. 我正在使用Ruby on Rails API(4.0版)来创建和更新发票。 The relationship between invoices and products is a has_many trough: relationship. 发票和产品之间的关系是has_many trough:关系。 Imagine I have product 1, 2, & 3. I am having trouble creating a new invoice that contains product 1 & 3. . 想象我有产品1、2和3。我在创建包含产品1和3的新发票时遇到了麻烦 When I run the code below I get the error: 当我运行下面的代码时,出现错误:

Unknown primary key for table invoices_products in model InvoicesProduct.

This error doesn't really make sense to me since InvoicesProduct is a join table and shouldn't require a primary key. 因为InvoicesProduct是一个联接表,并且不需要主键,所以这个错误对我来说真的没有意义。

One tricky part about the design is that it needs to track which employee added which products to the invoice, which is why invoices_product has employee_id . 关于设计的一个棘手的部分是,它需要跟踪哪个员工向发票中添加了哪些产品,这就是为什么invoices_product具有employee_id It does not seem to be the cause of the problem at the moment. 目前看来,这并不是问题的原因。 Here is the DB design of the tables in questions: 这是有问题的表的数据库设计:

发票通过发票有很多产品_产品表

InvoicesController InvoicesController

This is the code I currently have in the controller. 这是我目前在控制器中的代码。 The error message occurs on the first line of create: 错误消息出现在创建的第一行:

def create
  invoice = Invoice.new(create_invoice_params)
  invoice.created_by = @current_user
  # eventually need to set employee_id on each invoice_product,
  # but just need to get it working first
  # invoice.invoices_products.map!{|link| link.employee = @current_user }
  invoice.save
  respond_with invoice
end

def create_invoice_params
  params.fetch(:invoice).permit(:customer_id, :status_code, :payment_method_code, product_ids: [])
end

Invoice 发票

# /app/models/invoice.rb
class Invoice < ActiveRecord::Base
  validates_presence_of :customer
  validates_presence_of :created_by

  belongs_to :customer, inverse_of: :invoices
  belongs_to :created_by, inverse_of: :invoices, class_name: 'Employee'
  has_many :invoices_products, inverse_of: :invoice
  has_many :products, through: :invoices_products
end

InvoicesProduct InvoicesProduct

class InvoicesProduct < ActiveRecord::Base
  validates_presence_of :invoice
  validates_presence_of :product
  validates_presence_of :employee

  belongs_to :product, inverse_of: :invoices_products
  belongs_to :invoice, inverse_of: :invoices_products
  belongs_to :employee, inverse_of: :invoices_products
end

Product 产品

# /app/models/product.rb
class Product < ActiveRecord::Base
  validates :name, presence: true, length: { maximum: 100 }

  has_many :invoices_products, inverse_of: :product
  has_many :invoices, through: :invoices_products
end

Request 请求

This is what I've got in mind for a working request, the solution doesn't need to match this, but its what I've been trying 这是我对工作请求的考虑,解决方案不需要与此匹配,但是我一直在尝试

{
  "invoice": {
    "customer_id": "1",
    "product_ids": ["1", "5", "8"]
  }
}

I was able to fix the relationship by adding a primary key to the invoices_products . 我可以通过在invoices_products添加主键来解决这种关系。 For some reason I was under the impression that join tables did not require a primary key for has_many :through relationships. 由于某种原因,我给人的印象是联接表不需要has_many :through关系的主键。 However, looking at the example on the Rails guide site , the example join table does have a primary key. 但是,在Rails指南站点上查看示例 ,示例联接表确实具有主键。

That is because you are using has_many :through. 那是因为您正在使用has_many:through。 If you don't want id (or any other additional field) in the join table, use has_many_and_belongs_to instead 如果您不想在联接表中使用id(或其他任何其他字段),请使用has_many_and_belongs_to代替

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM