Forum OpenACS Development: Re: xotcl core cr procs throw out assigned item_id and assign a new one, why?

hi dave,

the Object Relational Database Interface http://openacs.org/xowiki/xotcl-core-db supports for object-saving basically two methods, save and save_new. While the basic idea of save is to perform an update operation (i.e. keep the same id (item_id, user_id, ...), the method save_new is intended to create new ids by itself. There is a lot of code that is based on this assumption. The "fundamental reason" for not passing the item_id to these occurrences of content_item.new is that this are not the intended sematics. The xotcl-core interface supports item_id for content_item.new: http://openacs.org/api-doc/proc-view?proc=%3a%3axo%3a%3adb%3a%3asql%3a%3acontent_item+proc+new

What do you want to achieve? allocate fresh id's in advance and pass it to save_new? The question is, what you gain by this.

Of course, it is possible to extend the interface of ::xo::db::CrItem save_new and pass it a fresh item_id. The code should check, whether the item_id is still fresh to avoid surprises. One can extend the interface it by defining your own classes, or extend it by providing a mixin, etc. One certainly can define a new method (with a different name) and use it where appropriate. One can certainly extend xotcl-core, but then one should as well extend the generic ::xo::db::Object save_new for consistency.

Hope that helps
-gustaf neumann

I think what is desired is to be able to pass in the id of the object to be created, AND have the code that creates the object use that id.

Every proc that creates a new object accepts the new object ID parameter; if it's an id, you have the id to create the object on, if it's null, you generate a new id.

The main reason I use that feature, is to implement double-click protection; the "add new whatever" form would have a generated ID as a hidden field, and if the OK button was hit twice, you would not get two objects, two copies of a forum posting, two credit card charges.

My goal was to extend an Xowiki Form which has a preassigned id which is never used.

In the new_request and generate method the item_id is set to one value. In the after_submit method it is set to a different value. That's why my code didn't work since it assumed the assigned id in the hidden variable of the form would be used to create the new xowiki page.

I can probably write a workaround that references the old form value in after_submit method to compare the old item_id to the newly assigned one.

if you have to write a workaround, how can we improve or at least maintain teachability, understandability, maintainability?
Dave, the easiest thing is to subclass Form (e.g. xowiki::WikiForm) and define your own Form-class (this is the oo recommended way to extend a class). Then define your own method "new_data" (based on the definitions of WikiForm.new_data and Generic::Form.new_data; the latter.new_data does the "save_new"). There you have full control about the saving operations for new items.

As mentioned before, be aware that you have to care about the validity and security of the passed id, since one cannot trust on from-data.

Jim: i see you point, using the fresh item_id as a "poor men's transaction code". i would not rely on this without further checking. The the storage operations in the db are quite late for double-click prevention, and not particularly well suited for meaningful error messages concerning double-clicks.