Rails 5 在连接中更改属性值时插入而不是更新 table
Rails 5 is inserting instead of updating when changing the value of attribute in the join table
我使用 has_many :through 关联建立了 HABTM 关系。我在更新联接 table 中的属性时遇到问题,因为它没有更新记录,而是在 table 中插入了一条新记录,创建了重复项。
我在创建索引和添加验证时尝试使用 UNIQUE 约束,但现在当我更新记录时出现验证错误或错误:
BatchesController 中的 ActiveRecord::RecordNotUnique#update
Mysql2::Error: 重复条目
提供一些背景信息:
- 我有4个table:manufacturing_orders,order_products,批次和批次_order_products(加入table)。
- 一个manufacturing_order有多个order_products。
- 还有一个manufacturing_order批次多
- 批次有很多order_products。
- 当我创建一个批次时,我复制了属于同一个 manufacturing_order 的所有 order_products,并且在表格中我可以为每个批次分配一个数量。
所以创建看起来工作正常,但是当我更新任何数量时它只是再次插入整个关系而不是更新现有关系。
型号manufacturing_order.rb:
class ManufacturingOrder < ApplicationRecord
has_many :batches, inverse_of: :manufacturing_order, dependent: :destroy
has_many :order_products, inverse_of: :manufacturing_order, dependent: :destroy
accepts_nested_attributes_for :order_products
accepts_nested_attributes_for :batches
end
型号order_product.rb:
class OrderProduct < ApplicationRecord
belongs_to :manufacturing_order
has_many :batches_order_products
has_many :batches, :through => :batches_order_products
end
型号batch.rb:
class Batch < ApplicationRecord
belongs_to :manufacturing_order
has_many :batches_order_products
has_many :order_products, :through => :batches_order_products
accepts_nested_attributes_for :batches_order_products
end
型号batches_order_product.rb:
class BatchesOrderProduct < ApplicationRecord
belongs_to :batch
belongs_to :order_product
validates :batch_id, uniqueness: { scope: :order_product_id }
end
控制器batches_controller.rb:
class BatchesController < ApplicationController
def new
manufacturing_order = ManufacturingOrder.find(params[:manufacturing_order_id])
order_products = manufacturing_order.order_products
@batch = Batch.new({
manufacturing_order: manufacturing_order,
order_products: order_products
})
end
def create
@batch = Batch.new(load_params)
if @batch.save
flash[:notice] = crud_success
redirect_to action: :index
else
flash[:error] = @batch.errors.full_messages.to_sentence
render action: :new
end
end
def edit
@batch = Batch.find(params[:id])
end
def update
@batch = Batch.find(params[:id])
if @batch.update_attributes(load_params)
flash[:notice] = crud_success
redirect_to action: :index
else
flash[:error] = @batch.errors.full_messages.to_sentence
render action: :edit
end
end
private
def load_params
params.require(:batch)
.permit(:name,
:date,
:manufacturing_order_id,
:status,
order_products: [],
order_products_ids: [],
batches_order_products_attributes: [:id, :quantity, :order_product_id]
)
end
end
这是分批的形式:
= bootstrap_form_for([@batch.manufacturing_order, @batch]) do |f|
= f.hidden_field :manufacturing_order_id
= f.text_field :name, label: 'Name'
= f.text_field :date
table
thead
tr
th= "Product"
th= "Quantity"
tbody
= f.fields_for :batches_order_products do |bop|
= bop.hidden_field :order_product_id
tr
td
= bop.object.order_product.name
td
= bop.text_field :quantity
= f.submit 'Save'
非常感谢任何帮助。谢谢!
更新:
这些是提交编辑表单时传递的参数。有什么线索吗?
{"utf8"=>"✓",
"_method"=>"patch",
"batch"=>
{"manufacturing_order_id"=>"8",
"name"=>"MAS",
"date"=>"07/05/2020",
"batches_order_products_attributes"=>
{"0"=>{"order_product_id"=>"12", "quantity"=>"77777777", "id"=>""},
"1"=>{"order_product_id"=>"13", "quantity"=>"9.0", "id"=>""},
"2"=>{"order_product_id"=>"14", "quantity"=>"7.0", "id"=>""}}},
"commit"=>"Guardar",
"manufacturing_order_id"=>"8",
"id"=>"7"}
编辑 2:我更新了嵌套表单以将 id 包含在隐藏字段中,如下所示:
= f.fields_for :batches_order_products do |bop|
= bop.hidden_field :order_product_id
= bop.hidden_field :id, value: @batch.id
= bop.object.order_product.name
= bop.text_field :quantity, label: ''
但是现在 Rails 在更新时抱怨这个:
ActiveRecord::StatementInvalid in BatchesController#update
Mysql2::Error: Unknown column 'batches_order_products.' in 'where clause': SELECT `batches_order_products`.* FROM `batches_order_products` WHERE `batches_order_products`.`batch_id` = 9 AND `batches_order_products`.`` IN ('9', '9', '9', '9', '9')
我不知道为什么 Rails 在 SQL 查询中添加最后一个奇怪的部分。
所以我终于想通了。
问题是连接 table 需要一个 ID 列来引用。 table 有一个 batch_id 和 order_product_id 的索引,但由于某种原因它不起作用,ActiveRecord 正在寻找一个 ID。添加它解决了问题。
感谢@max 给点意见。
class AddIndexToBatchesOrderProductsJoinTable < ActiveRecord::Migration[5.2]
def change
# add_index :batches_order_products, [:batch_id, :order_product_id], unique: true
add_column :batches_order_products, :id, :primary_key
end
end
我使用 has_many :through 关联建立了 HABTM 关系。我在更新联接 table 中的属性时遇到问题,因为它没有更新记录,而是在 table 中插入了一条新记录,创建了重复项。
我在创建索引和添加验证时尝试使用 UNIQUE 约束,但现在当我更新记录时出现验证错误或错误: BatchesController 中的 ActiveRecord::RecordNotUnique#update Mysql2::Error: 重复条目
提供一些背景信息:
- 我有4个table:manufacturing_orders,order_products,批次和批次_order_products(加入table)。
- 一个manufacturing_order有多个order_products。
- 还有一个manufacturing_order批次多
- 批次有很多order_products。
- 当我创建一个批次时,我复制了属于同一个 manufacturing_order 的所有 order_products,并且在表格中我可以为每个批次分配一个数量。
所以创建看起来工作正常,但是当我更新任何数量时它只是再次插入整个关系而不是更新现有关系。
型号manufacturing_order.rb:
class ManufacturingOrder < ApplicationRecord
has_many :batches, inverse_of: :manufacturing_order, dependent: :destroy
has_many :order_products, inverse_of: :manufacturing_order, dependent: :destroy
accepts_nested_attributes_for :order_products
accepts_nested_attributes_for :batches
end
型号order_product.rb:
class OrderProduct < ApplicationRecord
belongs_to :manufacturing_order
has_many :batches_order_products
has_many :batches, :through => :batches_order_products
end
型号batch.rb:
class Batch < ApplicationRecord
belongs_to :manufacturing_order
has_many :batches_order_products
has_many :order_products, :through => :batches_order_products
accepts_nested_attributes_for :batches_order_products
end
型号batches_order_product.rb:
class BatchesOrderProduct < ApplicationRecord
belongs_to :batch
belongs_to :order_product
validates :batch_id, uniqueness: { scope: :order_product_id }
end
控制器batches_controller.rb:
class BatchesController < ApplicationController
def new
manufacturing_order = ManufacturingOrder.find(params[:manufacturing_order_id])
order_products = manufacturing_order.order_products
@batch = Batch.new({
manufacturing_order: manufacturing_order,
order_products: order_products
})
end
def create
@batch = Batch.new(load_params)
if @batch.save
flash[:notice] = crud_success
redirect_to action: :index
else
flash[:error] = @batch.errors.full_messages.to_sentence
render action: :new
end
end
def edit
@batch = Batch.find(params[:id])
end
def update
@batch = Batch.find(params[:id])
if @batch.update_attributes(load_params)
flash[:notice] = crud_success
redirect_to action: :index
else
flash[:error] = @batch.errors.full_messages.to_sentence
render action: :edit
end
end
private
def load_params
params.require(:batch)
.permit(:name,
:date,
:manufacturing_order_id,
:status,
order_products: [],
order_products_ids: [],
batches_order_products_attributes: [:id, :quantity, :order_product_id]
)
end
end
这是分批的形式:
= bootstrap_form_for([@batch.manufacturing_order, @batch]) do |f|
= f.hidden_field :manufacturing_order_id
= f.text_field :name, label: 'Name'
= f.text_field :date
table
thead
tr
th= "Product"
th= "Quantity"
tbody
= f.fields_for :batches_order_products do |bop|
= bop.hidden_field :order_product_id
tr
td
= bop.object.order_product.name
td
= bop.text_field :quantity
= f.submit 'Save'
非常感谢任何帮助。谢谢!
更新: 这些是提交编辑表单时传递的参数。有什么线索吗?
{"utf8"=>"✓",
"_method"=>"patch",
"batch"=>
{"manufacturing_order_id"=>"8",
"name"=>"MAS",
"date"=>"07/05/2020",
"batches_order_products_attributes"=>
{"0"=>{"order_product_id"=>"12", "quantity"=>"77777777", "id"=>""},
"1"=>{"order_product_id"=>"13", "quantity"=>"9.0", "id"=>""},
"2"=>{"order_product_id"=>"14", "quantity"=>"7.0", "id"=>""}}},
"commit"=>"Guardar",
"manufacturing_order_id"=>"8",
"id"=>"7"}
编辑 2:我更新了嵌套表单以将 id 包含在隐藏字段中,如下所示:
= f.fields_for :batches_order_products do |bop|
= bop.hidden_field :order_product_id
= bop.hidden_field :id, value: @batch.id
= bop.object.order_product.name
= bop.text_field :quantity, label: ''
但是现在 Rails 在更新时抱怨这个:
ActiveRecord::StatementInvalid in BatchesController#update
Mysql2::Error: Unknown column 'batches_order_products.' in 'where clause': SELECT `batches_order_products`.* FROM `batches_order_products` WHERE `batches_order_products`.`batch_id` = 9 AND `batches_order_products`.`` IN ('9', '9', '9', '9', '9')
我不知道为什么 Rails 在 SQL 查询中添加最后一个奇怪的部分。
所以我终于想通了。
问题是连接 table 需要一个 ID 列来引用。 table 有一个 batch_id 和 order_product_id 的索引,但由于某种原因它不起作用,ActiveRecord 正在寻找一个 ID。添加它解决了问题。
感谢@max 给点意见。
class AddIndexToBatchesOrderProductsJoinTable < ActiveRecord::Migration[5.2]
def change
# add_index :batches_order_products, [:batch_id, :order_product_id], unique: true
add_column :batches_order_products, :id, :primary_key
end
end