Re: Need help building an EOQualifier with session values
Re: Need help building an EOQualifier with session values
- Subject: Re: Need help building an EOQualifier with session values
- From: Chuck Hill <email@hidden>
- Date: Tue, 23 May 2006 11:28:32 -0700
Hi Reid,
On May 23, 2006, at 10:27 AM, Reid Bundonis wrote:
Ken, Mark, and Chuck,
Thanks for taking the time out of your weekend to help me with the
qualifier statement. So, enough with this WO stuff, anyone have
advice on getting a baby with a cold to sleep?
If we knew how to do that, I doubt we would still be working for a
living! :-)
If the rest of this post in incoherent, I apologize in advance.
Sleep deprivation and WO development do not mix.
First, let me provide a bit more detail about the structure of the
db and what I am trying to do. Reading your posts makes me think
that my thinking is a bit muddled and I am trying to turn something
remarkably simple into something complex and ugly.
First, the database: I have four entities, User (userID [int],
firstName [string], lastName [string], password [string] clientID
[int]), Client (clientID [int], clientName [string]) , Process
(processID [int], processName [string], clientID [int]), and Result
(resultID [int], startTime [date], stopTime [date], processID
[int]). All relationships use a primary and foreign key ints to
create the relationship. Each Client can have many Users but each
user has only one client. Each Client can have many Processes but
each process belongs to only one client, and each Process can have
many Results.
Next, what I am trying to accomplish is that when a User logs in,
the User is held in the Session so I can pull unique items out
during the remaining time in the app. For example, when the user
logs in, bind a WOString to session.user.client.clientName or
session.user.firstName, etc. and I have a customized page for the
individual with doing no work other that initiating the session and
storing the logged user there. That is the easy part as on login I
am setting sess.setUser( (User) ... and session has a key for User
to hold the values. From the interface side, this works. I am
able to bind to WOStrings without trouble and the values of the
stored (logged in) User are displayed.
So, what I was trying to do was on login, since I am storing the
User in session, I assumed that I had access to the full
relationship tree.
You do.
For example, the WOString binding of session.user.client.clientName
works in the interface and returns the proper value, so I though I
would be able to grab the returned value and stick it in a qualifier.
Yes, that will work.
Thus, when User Bob, who is a member of Client Prentendco, logs
in, I know he is a member of user.client and the clientName
attribute is Prentendco. As mentioned above, I can display this
with WOStrings and binding to the session.user... attributes. What
I would like to do is dynamically grab the clientName value, as I
know it is unique to each user since the relationship defines one
client per user and then thus pull up a repetition of all the
processes that belong to the user's client.
Now here you start to wander off the path. A User is related to a
Client. A Client has Processes. So why drag in the client's name?
The WO way is to use the Client directly.
This way, when Bob, of client Pretendco, logs in, I will get all of
Pretendco's processes. When Mary, of AlterCo, logs in, I will get
all of AlterCo's processes, etc. As Mark pointed out, I should be
using the whole object
Obviously, if I manually set the value, I am good:
NSMutableArray args = new NSMutableArray();
args.addObject("client.clientName");
I am assuming the line above is a typo. and should be
args.addObject(session().valueForKeyPath("user.client.clientName"))
or some such.
qual = EOQualifier.qualifierWithQualifierFormat("client.clientName
= 'Pretendco'", args);
fs = new EOFetchSpecification("Process", qual, null);
I want to be able the make the session.user.client.clientName value
and throw it at the qualifier. However, when ever I use the code
suggestion, I get either an attempt to enter a null (see below
regarding Ken's suggestion for println) into the NSArray or I throw
an exception stating that there is no key for
user.client.clientName or anything else.
If this code is in a component, it should be:
args.addObject(session().valueForKeyPath("user.client.clientName"))
Or, if you want to avoid KVC as it is really needless here:
args.addObject(((Session)session()).user().client().clientName())
or, as I was suggesting earlier:
args.addObject(((Session)session()).user().client())
with
qual = EOQualifier.qualifierWithQualifierFormat("client = %@'", args);
Which is more the way of doing it.
The _real_ WO way of doing this is to model the one to many
relationship processes() from Client to Process. Thus you can
eliminate the fetch entirely and just write
NSArray processes = ((Session)session()).user().client().processes();
Or you can use this directly in a binding as
list = session.user.client.processes;
One line. THAT'S the WO way. :-)
However, as Ken pointed out with the println statement, I've
discovered I do NOT have access to this value. When trying the
print the line, I throw an exception that the key is unreachable
(lookup of unknown key: 'user.client.clientName'.).
That is because a path with a "." in it needs to be passed to
valueForKeyPath.
If I change the println statement to valueForKeyPath, then I do not
throw the exception, but instead get a result of null regardless of
the key path. I tried user.firstName (System.out.println("Client
name is "+session().valueForKeyPath("user.firstName"));) as well as
the full path that I think I want, user.client.clientName).
Are you perhaps calling this on session before setting the user?
How is it that I have access to these values through interface
bindings but not programmatically? Am I missing something
remarkably obvious in the session? I am confused that I am able to
access the values through the interface using bindings, but not
programmatically.
I am wondering if it may be a timing issue and the user not being in
the session yet.
Again, thanks everyone for the help and attempts to decode the
ramblings of the sleep deprived.
:-P
Chuck
On May 21, 2006, at 9:51 AM, Ken Anderson wrote:
Reid,
Just so I understand what you want to do - you're trying to fetch
Process records from the database for the client, right?
My first question is, since you say you have a client object, why
are you using the clientName instead of the client object? You
should really have a relationship in Process called 'client',
which is a relationship to the Client entity based on the name (or
better, a unique integer primary key so the client's name can
change without breaking the database).
To address your specific question, are you sure that
user.client.clientName is getting the result you want? Have you
tried:
System.out.println("Client name is "+session().valueForKey
("user.client.clientName"));
Otherwise, if Process has an attribute called 'clientName' that
matches the clientName in the client object, this code should
work. It would help if you gave more information about the model...
Ken
Ken's post has already pointed out how your approach, on the
surface anyway, raises a little warning flag. The code for what
he's talking about would be something like:
NSArray bindings = new NSArray( session().valueForKey
("user.client") );
qual = EOQualifier.qualifierWithQualifierFormat("client = %@",
bindings );
fs = new EOFetchSpecification("Process", qual, null);
You try and store and deal with complete objects when you can, and
in this case EOF will query based on the join attribute you
provided in the (possibly hypothetical) "client" relationship.
Minor points, note that you can construct and NSArray of one
object without going through the Object step, and that you don't
need to cast to Session to use valueForKey. However, if client is
a public variable or (preferably) accessor method in your Session,
you could change that line to:
NSArray bindings = new NSArray( ((Session)session()).user
().client() );
If Bob (in your example) has multiple clients, however, the above
doesn't make sense. If that's the case, and he can choose the
client he's currently dealing with, you could just add a
currentClient variable and accessors (returning a Client object)
to the Session to indicate his choice. Then the code becomes:
NSArray bindings = new NSArray( ((Session)session
()).currentClient() );
qual = EOQualifier.qualifierWithQualifierFormat("client = %@",
bindings );
fs = new EOFetchSpecification("Process", qual, null);
valueForKeyPath not valueForKey
Chuck
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Webobjects-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
40global-village.net
This email sent to email@hidden
--
Coming in 2006 - an introduction to web applications using WebObjects
and Xcode http://www.global-village.net/wointro
Practical WebObjects - for developers who want to increase their
overall knowledge of WebObjects or who are trying to solve specific
problems. http://www.global-village.net/products/practical_webobjects
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Webobjects-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden