This is a long one, but in summary the last problem to overcome is
that on @event.save the payment_installments are being validated, but
then are never updated (before_update is never called).
Why would the update be aborted? valid? returns true and if I check
the values of the model object at after_validation_on_update the
values look all good and are the same as what was entered on the form.
Any ideas would be most helpful...
Here are the full results of my investigation:
There seems to be a few examples on various places on the net that
cover handling validation errors from multiple models when _creating_
a new record. Unfortunately, there are exactly zero examples on how
to handle validation errors on multiple models when _updating_
existing records.
One thing I came up with is a mashup of this:
errors-in-rails/
and this:
http://www.edwardthomson.com/blog/2006/04/
rails_validations_with_multipl.html
@pi = @event.payment_installments.find(installment_form[:id].to_i)
@pi.name = installment_form["name"]
@pi.value = installment_form["value"]
@pi.due_date_as_text = installment_form["due_date"]
if !@pi.save
@pi.errors.each { |k,m| @event.errors.add(k,"on Payment
Installment line #{i+1}, " +m) }
end
@event.attributes=(params[:event])
if @event.errors.empty? && @event.save
flash[:notice] = 'Event was successfully updated.'
redirect_to :action => 'show', :id => @event
else
... set various stuff here ready to reshow form
render :action => 'edit'
end
This pretty much works, a nice error is printed at the top of the
screen.
Of course, nothing is perfect, and it doesn't preserve the users
edited fields when it reshows the fields. I believe this is because
the @event object does not contain the updated values for the
payment_installments children. In the above code, I take a copy of
the object and save that to the database, I do not edit the
@event.payment_installments array of objects as I can't seem to
figure out how to do this.
It seems that this is still an issue, I still require the ability to
edit the values held in memory under event.payment_installments.find
(id).name for example. In looking at the ActiveRecord doco I should
be able to utilise the write_attribute method to do this, but it has
no effect. Ah, hang on. The find method always seems to pull from
the database and ignore the values in memory. But, I may be way off
track here. My suspicion is that find is pulling a copy of the
object from the database and updating that. This looks as though
using find with write_attribute maybe a useless combination, I'm
updating a copy instead of the actual attribute in memory.
Although, I seem to remember coding one attempting iterating through
the @event.payment_installments array (not using find) and then
using .name = installment_form["name"] but that had no effect. I
just tested that again, code is (please forgive my non-ruby-esq code):
j = 0
while j < @event.payment_installments.length
if @event.payment_installments[j].id == installment_form[:id].to_i
@event.payment_installments[j].name = installment_form["name"]
@event.payment_installments[j].value = installment_form["value"]
@event.payment_installments[j].due_date_as_text =
installment_form["due_date"]
end
j += 1
end
@event.attributes=(params[:event])
if @event.save
flash[:notice] = 'Event was successfully updated.'
redirect_to :action => 'show', :id => @event
else
... set various stuff here ready to reshow form
render :action => 'edit'
end
Believe it or not, this _almost_ works! The validation picks up
errors for the payment_installment model, it also shows the user
entered values on the form redraw, however, for some reason, when it
validates correctly, the data doesn't change! AAAAHHHHH!
Frustration setting in...
What on earth could be happening here? Why does it fail validation
and looks fine (on the form), but when it passes validation, the data
doesn't change? In the log, I see it selecting data from the table,
but then it never updates anything... Why would it attempt to
validate something it was never going to save? I have a validation
method in my model, and it prints to the log, this is appearing in my
log, so with good data, the validation is being called as if it's
going to save.
Dan