I am running ActiveRecord 3.2.6. Given that I have these model definitions:
My account model
class Invoice < ActiveRecord::Base
has_many :items, :autosave => true, :dependent => :delete_all
attr_accessible :recipient_email
def items=(ary)
super ary.map{|item| item.is_a?(Hash) ? items.build(item) : item}
end
end
Model of my product
class Item < ActiveRecord::Base
belongs_to :invoice
attr_accessible :amount, :description, :invoice_id, :value
end
My goal is to save the elements of the account directly in the model. This works without problems when the invoice has just been created. One call Invoice#save!and everything will be 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 items in Invoiceexisting ones, it deletes old items before saving new items.
> i = Invoice.find(1)
> i.items = [{amount: 10, description: "Less buggy objective relational mappers", value: 1337.00}]
SQL (0.8ms) DELETE FROM items WHERE id IN (1, 2)
> i.save!
SQL (1.0ms) INSERT INTO "items" [...]
(192.6ms) commit transaction
How can I tell ActiveRecord to remove old items only when called Invoice#save!? Or is this a bug in ActiveRecord?
EDIT: My question is clarified
, DELETE (i.items = ...), , , (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
hapens
DELETE (2). (3). ( ).