On Mar 24, 2009, at 8:44 AM, Mark Wardle wrote:
When is the appropriate time to create an editingcontext - within a
component's constructor?
I do the same thing that Kieran suggested. My component has an
editingContext() method which creates its own editing context.
If so, is it appropriate to pass a handle to
the editingcontext between components? For example, I have a
UserEdit
component, that takes a User as a binding, and allows a user to edit
that user's details (subject to permissions).
You could do that as long as it's okay to mess with that editing
context.
But you could run into trouble, for example if you start editing
your User
object and then go somewhere else in the application, modify
something and
save then if the editing context is the same as the one used for
these
components then you may be saving the pending edits to the User
object as a
side effect and not exactly what the user would expect.
Soo... what I do is, if your UserEdit component is being handed the
User
object then it can simply get a copy of of the user object into the
UserEdit's local editing context. I do this in a couple of
different ways.
Here's the one with less code:
/** Returns copy of user object in the UserEdit's local editing
context */
public User user() {
User user = (User) valueForBinding("user");
return user.localInstanceIn(editingContext());
}
But you could have trouble here when they start editing the user
object and
then in a subsequent request you are handed in a different user
object. All
of a sudden you will start editing a different user object and you
still
have pending edits for the other user object.
So what I do is usually the version that involves a bit more code.
I you
are using project Wonder and your component inherits from
ERXComponent then
I usually do this in preAppendToResponse as follows :
public preAppendToResponse(WOResponse response, WOContext context) {
// See what user object we're being handed in
User aUser = (User) valueForBinding("user");
// Convert it to our local editing context
aUser.localInstanceIn(editingContext());
// If the user handed in is a different user from the one
we're
currently editing...
if (user != aUser) ) {
// ... then throw away any pending edits ...
editingContext().revert();
// ... and start using that user object
user = aUser;
}
}
public User user() {
return user;
}
Now in the real world sometimes I get handed in a brand new object
which was
created in an external editing context and which is okay to mess
with. For
example let's say the parent component is the one that hands in the
user
object to the UserEdit component, and let's say that it was created
like
this prior to be handed in to UserEdit:
EOEditingContext newEditingContext =
ERXEC.newEditingContext();
User aUser = new User();
newEditingContext.insertObject(aUser);
aUser.setFoo("foo");
Then your user edit is handed in this user object. In this case I
assume
that I can use that editing context and can have the following bit
of code
in preAppendToResponse():
// See what user object we're being handed in
User aUser = (User) valueForBinding("user");
// See if it's a new object and not exactly the one we're
currently
editing
if (aUser.isNewObject() && aUser != user) {
// use the externally created editing context as the
local
editing context
_editingContext = aUser.editingContext();
user = aUser;
}
Ok... so that's close to what I do normally. Not sure if it's the
best way,
but it seems to work for me.
What if I then have subcomponents that need to use the parent
editing
context? Is it appropriate to get the parent's editingcontext from
the
EO itself?
I document this for the component. For example, in your UserEdit
component
documentation I would mention that it uses its own editing context
for
editing unless the user object handed in is a new object that has
not been
saved to the database yet.
Once I start thinking about that, it looks like I'm writing lots of
code which is fairly repetitive and thought that there must be a
better way? Am I missing something obvious? I don't want to make
things highly modal, and I usually don't wish to preserve state
between components unless the user specifically requests it.
Yes I've thought about abstracting that code so I don't repeat it.
The user
i-var and binding could be called document.
And have that code in a superclass in preAppendToResponse(). Then
the
UserEdit component would extend that component. If your subclass
has some
code in preAppendToResponse then you would have to call
super.preAppendToResponse() to make sure that logic is not skipped.
______________________________________________________________________
This email has been scanned by the MessageLabs Email Security System.
For more information please visit
http://www.messagelabs.com/email______________________________________________________________________