保存模型时删除关联的记录

我正在运行ActiveRecord 3.2.6。 鉴于我有这些模型定义:

我的发票模型

class Invoice  true, :dependent => :delete_all attr_accessible :recipient_email # This is just a simple wrapper with allows me to build multiple # items at once and to specify them as a Hash instead of Item.new. def items=(ary) super ary.map{|item| item.is_a?(Hash) ? items.build(item) : item} end end 

我的物品模型

 class Item < ActiveRecord::Base belongs_to :invoice attr_accessible :amount, :description, :invoice_id, :value end 

我的目标是将发票项目直接保存在模型中。 当新创建发票时,这没有问题。 一次致电Invoice#save! 一切都得救了。

 > i = Invoice.new(:recipient_email => "foobar@example.org") > i.items = [{amount: 10, description: "Bottles of Milk", value: 0.40}, {amount: 1, description: "Shipping fee to Antarctica", value: 217.38}] > i.save! SQL (23.5ms) INSERT INTO "invoices" [...] SQL (0.3ms) INSERT INTO "items" [...] SQL (0.2ms) INSERT INTO "items" [...] => true 

但是,当我尝试更新已存在的Invoice中的项目时,它会在保存新项目之前删除旧项目。

 # Load invoice ID 1, with two items: ID 1 and ID 2. > i = Invoice.find(1) # It deletes the old items here > i.items = [{amount: 10, description: "Less buggy objective relational mappers", value: 1337.00}] SQL (0.8ms) DELETE FROM items WHERE id IN (1, 2) # But it should delete the new items here, before inserting the new items, # wrapping everything in a transaction. > i.save! SQL (1.0ms) INSERT INTO "items" [...] (192.6ms) commit transaction 

如何在Invoice#save!时告诉ActiveRecord删除旧项目Invoice#save! 叫做? 或者这是ActiveRecord中的错误?

编辑:我的问题 – 澄清

我不希望在分配项目时运行DELETE查询( i.items = ... ),但是当保存包含项目的发票时( i.items = ... invoice.save! )。 它应该标记旧项目的删除和新项目的插入,然后在invoice.save上执行查询invoice.save! 。 这可能与ActiveRecord有关吗?

编辑2:进一步澄清

由于有些人不能正确回答问题,因此需要进一步澄清。 我必须承认,这非常复杂。 所以这是实际发生的事情和我想要发生的事情之间的区别。

我想要的是

不会发生。 我希望它发生。 这完全是虚构的。 将它与上面的列表进行比较,看看差异。

 # (1) Load invoice ID 1, with two items: ID 1 and ID 2. > i = Invoice.find(1) # (2) Assign new items, delete the old ones. New stuff exists in memory, not in database > i.items = [{amount: 10, description: "Less buggy objective relational mappers", value: 1337.00}] # (3) Save everything to database. Run queries. > i.save! (0.0ms) begin transactions SQL (0.8ms) DELETE FROM items WHERE id IN (1, 2) SQL (1.0ms) INSERT INTO "items" [...] (192.6ms) commit transaction 

实际上是什么

DELETE查询在第(2)点运行。 但它应该在第(3)点运行。 (与上面的清单相比)。

它将删除旧项目,因为您将关联配置为自动保存

 has_many :items, :autosave => true, :dependent => :delete_all 

删除自动保存并重试,它将工作。

由于您希望在分配中添加操作,我相信这应该有效:

  def items=(ary) super(ary.map{|item| item.is_a?(Hash) ? items.build(item) : item} + self.items) end