I have two AR descendant classes, A and B, where A has_many B’s.
I have an action where I create a new (unsaved) A. It then renders to
another page that in turn posts to an action that creates several B’s
that are then associated to A (but not saved yet since A has not been
saved).
If I call A.save! and there is a problem saving one of the B’s, I
redisplay my form and prompt the user to fix the data. Looking at the
log file, I can see the apparently successful SQL call to save the row
for A as well as the SQL error for B.
(Note that throughout the process of fixing the B objects, the A object
is not changed.)
Once the data is fixed, the call to A.save! happens again, and there is
no INSERT statement for table A. The save for B fails with a foreign
key constraint failure (no A row to point to). There are no A rows in
the database so this makes sense.
Calling A.new_record? before A.save! shows that the A object thinks it
is not saved. However, no INSERT statement for A ever occurs after that
first, successful save.
I’m guessing that when the first save! call occurs, that the A object
thinks it saved to the database even though it didn’t (because of the
child row failures). Then, later, there is no attempt to re-save the A
object and the B objects fail to save because there is no A object
available. What’s confusing is that A returns “true” to new_record? and
then no INSERT occurs.
I think I can get around this problem by doing A.save! before I add any
B’s to it. But this seems like a bug.
Anybody have any insight into the intricacies of save! with a has_many
relationship?
1st call to save!: The INSERT for table A succeeded because the INSERT
for table B tries to use foreign key id 191 as the foreign key to A.
The INSERT for table B fails.
2nd call to save!: No INSERT statement is executed for A. The INSERT
for table B tries to use foreign key id 191 as the foreign key to A.
The INSERT for table B fails because there is no such A row with id 191.
Not only is the INSERT not being retried for A, but the child rows are
remembering the original A id and failing for that reason.
But I believe the real problem is that I’m trying to build up my
object in two different actions that post from 2 different pages. So
I’m going to create a separate model object (not to be saved) to act as
a value object to help me build my real object in the 2nd step.
Because I’m trying to build my object across multiple submits, I’m
saving it to the flash and trying to keep up with its state as errors
occur in various submits. And clearly, it isn’t working.
An easy approach is to use a candidate record that you save as you go.
Then
you can use separate validation rules for the candidate and completed
models
pretty convenient - and easily ‘complete’ the candidate when the
wizard’s
done.
Quickly: Would Rails benefit from the use of form model objects -
objects whose purpose is to keep track of the state of a form? (I think
the answer is yes).
Yes, but I think they would be mis- and over-used. Consider how far
Rails
has come without them.
Should we always go down the path of one form ↔ one model object no
matter what (you may have many intermediate steps that you need to do in
many forms in order to build your object - how is that best
accomplished)?
Thanks for the responses. There are a couple of issues here.
The database error is happening because the length of one of the
columns is too long. Perhaps some validates_length_of is appropriate
here.
But I believe the real problem is that I’m trying to build up my
object in two different actions that post from 2 different pages. So
I’m going to create a separate model object (not to be saved) to act as
a value object to help me build my real object in the 2nd step.
Because I’m trying to build my object across multiple submits, I’m
saving it to the flash and trying to keep up with its state as errors
occur in various submits. And clearly, it isn’t working.
This all has me thinking about the RESTful thing and I will post about
that at a higher level soon.
Quickly: Would Rails benefit from the use of form model objects -
objects whose purpose is to keep track of the state of a form? (I think
the answer is yes).
Should we always go down the path of one form <-> one model object no
matter what (you may have many intermediate steps that you need to do in
many forms in order to build your object - how is that best
accomplished)?
I can see your point about the mis and over-use of form models - on the
other hand, aren’t we just misusing regular models and/or views and/or
controller methods when we use regular models to hold non-trivial form
state?
In my particular case, I have an upload file step and then a data
transformation step, and it is totally valid to deal with two objects
when that much work is going on.
Wes
This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.