删除相关记录时,模型保存 [英] Delete associated records when model is saved

查看:119
本文介绍了删除相关记录时,模型保存的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am running ActiveRecord 3.2.6. Given I have these model definitions:

class Invoice < ActiveRecord::Base
  has_many :items, :autosave => 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

我的目标是直接保存在模型中的发票项目。这工作没有问题,是新创建的发票时。一个呼叫发票#保存!,一切都将被保存。

My goal is to save the invoice items directly in the model. This works without problems, when the Invoice is freshly created. One call to Invoice#save! and everything is saved.

> 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 

然而,当我尝试更新的项目发票已经存在,它就会删除旧项目之前,我保存新项目。

However, when I try to update the items in an Invoice that already exists, it deletes the old items before I save the new items.

# 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

我怎么能告诉ActiveRecord的删除旧的项目仅在发票#保存!被称为?或者,这是ActiveRecord的一个错误?

How can I tell ActiveRecord to delete the old items only when Invoice#save! is called? Or is this a bug in ActiveRecord?

我不希望删除查询时,该项目被分配到运行(i.items = ... >),但保存包含项目的发票时( invoice.save!)。它应标记为删除的旧项目和insertation新的项目,然后再执行对 invoice.save查询!。这可能与ActiveRecord的?

I do not want the DELETE queries to run when the items are assigned (i.items = ...), but when the invoice containing the items is saved (invoice.save!). It should mark the old items for deletions and the new items for insertation and then execute the query on invoice.save!. Is this possible with ActiveRecord?

由于一些不明白的问题的权利,进一步澄清。我必须承认,这是pretty的复杂。因此,这里的区别是,真正发生什么,我希望发生的。

As some do not get the question right, some further clarifications. I must admit, this is pretty complex. So here is the difference between what actually happens and what I want to happen.

本的的发生。我的需要的它发生。这完全是虚构的。把它比作上市上面看到的差异。

This does not happen. I want it to happen. This is completely fictitious. Compare it to the listing above to see the difference.

# (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

究竟hapens

删除查询运行点(2)。但它应该运行点(3)。 (比较上面列表)。

What actually hapens

The DELETE query runs on at point (2). But it should run at point (3). (Compare to above listing).

推荐答案

既然你想添加的分配行为,我认为这应该工作:

Since you want append action in assignment, I believe this should work:

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

这篇关于删除相关记录时,模型保存的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆