В счете-фактуре много записей:
class Invoice < ActiveRecord::Base
has_many :invoice_entries, :autosave => true, :dependent => :destroy
validates_presence_of :date
end
class InvoiceEntry < ActiveRecord::Base
belongs_to :invoice
validates_presence_of :description
end
Предположим, у нас есть один счет в базе данных:
id: 1
date: '2013-06-16'
и в нем есть две записи в счетах:
id: 10 id: 11
invoice_id: 1 invoice_id: 1
description: 'do A' description: 'do C'
Теперь у меня есть новые записи в счетах:
id: 10
description: 'do B' description: 'do D'
(Existing invoice entry (New invoice entry
with updated description) without id)
Я хочу, чтобы в счете-фактуре были только эти новые записи счета-фактуры (это означает, что запись счета-фактуры с id=11
должна быть удалена).
invoice.invoice_entries = new_invoice_entries
, кажется, делает половину работы. Он удаляет запись счета-фактуры с id=11
, создает новую запись счета-фактуры с описанием 'Do D'
, но не обновляет описание записи счета-фактуры с id=10
с 'Do A'
на 'Do B'
. Я предполагаю, что когда Rails видит существующий id
в new_invoice_entries
, он полностью игнорирует его. Это правда? Если да, то в чем причина этого?
Мой полный код ниже. Как бы вы решили эту проблему? (Я использую Rails 4, на случай, если он упрощает код.)
# PATCH/PUT /api/invoices/5
def update
@invoice = Invoice.find(params[:id])
errors = []
# Invoice entries
invoice_entries_params = params[:invoice_entries] || []
invoice_entries = []
for invoice_entry_params in invoice_entries_params
if invoice_entry_params[:id].nil?
invoice_entry = InvoiceEntry.new(invoice_entry_params)
errors << invoice_entry.errors.messages.values if not invoice_entry.valid?
else
invoice_entry = InvoiceEntry.find_by_id(invoice_entry_params[:id])
if invoice_entry.nil?
errors << "Couldn't find invoice entry with id = #{invoice_entry_params[:id]}"
else
invoice_entry.assign_attributes(invoice_entry_params)
errors << invoice_entry.errors.messages.values if not invoice_entry.valid?
end
end
invoice_entries << invoice_entry
end
# Invoice
@invoice.assign_attributes(date: params[:date])
errors << @invoice.errors.messages.values if not @invoice.valid?
if errors.empty?
# Save everything
@invoice.invoice_entries = invoice_entries
@invoice.save
head :no_content
else
render json: errors.flatten, status: :unprocessable_entity
end
end