[ZPatterns] _v_dm_ KeyError calling get_transaction().abort()
Itai Tavor
[email protected]
Tue, 9 Oct 2001 12:08:28 +1000
Phillip J. Eby wrote:
>At 09:33 AM 10/9/01 +1000, Itai Tavor wrote:
>
>>Not quite sure what you mean by "get your self object again" - do
>>you mean do self=self.getItem(self.id)? This trickery is a bit over
>>my head...
>
>Just to explain more clearly what's going on, I thought I'd jump in
>for a second...
>
>ZPatterns objects retrieved from a Rack are not guaranteed to remain
>valid across transactional boundaries. In particular, aborting a
>transaction (even a subtransaction) guarantees that any references
>you have to a DataSkin will be invalid. You *must* re-retrieve the
>object from the Rack, or, in the case of a non-rackmounted DataSkin,
>re-retrieve it from its container. My suggestion for the code would
>be something like:
>
>id, DM = self.id, self._v_dm
>get_transaction().abort()
>self = DM.getItem(id)
>
>Thus, self is now a reference to an object in the *new* transaction
>space. It will have all its "magic" properly in place, where the
>aborted object will not.
>
>Please note that if any other references to DataSkins which were
>saved before the aborted transaction are used, they will also be
>invalid and cause errors.
>
>Technically speaking, references should not be held even across a
>subtransaction commit operation, but this doesn't usually cause many
>problems in practice. The only potential issue with a commit is
>that the Rack's per-transaction cache will be cleared, so when using
>virtual (e.g. SQL) objects, a post-commit retrieve might return an
>object which is not the "same" object as the one you hold a
>reference to. This is only a problem if you do such a thing, of
>course.
Thanks for the explanation. Until I find a better way to approach the
whole problem, I'll use your code snippet.
>>Could you please describe how you would solve this problem? I'd
>>really like to know if there is a better approach.
>>
>>Just to make sure you understood my problem correctly: The edit
>>method modifies the object, and possibly modifies and creates other
>>related objects, with values submitted in a form. If any of these
>>actions cause errors, these are added to an 'errors' dictionary. I
>>then roll back all the changes and display the errors by rendering
>>the original form. The need to abort came from the fact that the
>>form is rendered while the object is in its new, invalid state,
>>because the changes have not been rolled back yet.
>
>Hm. My usual approach to handling this is to just throw an error
>when a problem is found, albeit a fancy error text explaining the
>problem, and ask the user to press the back button to go back and
>correct.
This is certainly the easiest way, but IMHO it's bad UI, for two
reasons. First, all errors should appear at once. I don't want to
make a user fix one error, submit the form, get a 2nd error, submit
the form again... Second, it's much easier for a user to fix errors
when she can see them highlighted in the actual form. My error
handling would be a whole lot simpler if I didn't believe that it's
important to provide this feature...
>However, I think the simple way to do what you want is probably just
>to pre-render the form *before* you do the operations which might
>cause errors. If you get an error, just raise the pre-rendered
>form. Of course, it's more complex if you embed the error text
>multiple places in the form...
Won't work because the form displays the error messages, so it can't
be rendered before the error messages are collected...
Back to the drawing board. I wonder if the approach Steve hinted on
might be more helpful for my requirements.
--
--
Itai Tavor -- "Je sautille, donc je suis." --
[email protected] -- - Kermit the Frog --
-- --
-- "If you haven't got your health, you haven't got anything" --