On 2012-03-29, at 3:22 PM, Paul Hoadley wrote: Hi David, On 30/03/2012, at 4:11 AM, David Holt wrote: On 2012-03-29, at 8:51 AM, Ramsey Gurley wrote:
On Mar 29, 2012, at 2:31 AM, Paul Hoadley wrote:
Anyway, the subject above is probably a misnomer: I'm not trying to create particularly complex objects, but I am trying to do something outside CRUD, which is pretty much all I've ever done with D2W before. In the model, a Billable object has an optional to-one relationship to Invoice. When I create a Billable, it initially has no related Invoice. Later I will create an Invoice for a client, and collect together some set of Billables, and the relationship is created at that time. And that's the bit I need a pattern for: Invoice creation. Billable also has a mandatory relationship to Practice (i.e., a client), and a startTime timestamp. When I go to create an Invoice, I'd give the Invoice a date and select a Practice, and then I want to add, say, all of the Billables that (a) belong to no other Invoice, (b) point to the same Practice, and (c) have a startTime that falls before the new Invoice.date.
Well, you can just set the practice, the invoice date, and then save changes. In Invoice.willInsert() fetch the billables and add them to the relationship just before the save takes place. :-) Or is that too automatic?
I would probably do it in my Invoice init() method. Get the practice from thread storage (assuming you select it somehow and can save it in thread storage at that point) Set the date to current time Fetch billables that match your criteria Set the relationship to billables.
Yeah, OK, and then the billables relationship would be editable before I save the Invoice. Now, humour meāgive me an example of how I can "select it somehow and save it in thread storage". :-)
Sure. Create a custom link component and display it on your list of practices. The link has a custom method that sets your selectedPractice on the session in thread storage. This way you can access it from the rules as well as your model classes or application.
This is a very cool pattern that allows you to do interesting things with ERXNavigationMenu, but that's a topic for another day.
Here's an example for selecting a working group from a list:
public WOComponent view() { WorkingGroup selectedWG = (WorkingGroup) object(); ((Session) session()).setSelectedWG(selectedWG); NSArray<Forum> forums = selectedWG.forums(); Forum aForum = (Forum)forums.lastObject(); ((Session) session()).setSelectedForum(aForum); NSLog.out.appendln("The working group is " + selectedWG); return (WOComponent) ((Session)session()).navController().listMyWGTopics(); }
the line that sets the selected working group in the session is what you're worried about.
and in the session you have code like this:
protected WorkingGroup _selectedWG;
public WorkingGroup selectedWG() { return _selectedWG; }
public void setSelectedWG(WorkingGroup selectedWG) { _selectedWG = selectedWG; ERXThreadStorage.takeValueForKey(selectedWG(), "selectedWG"); }
public void awake() { super.awake();
// if we have a selected working group, keep track of it if (selectedWG() != null) { ERXThreadStorage.takeValueForKey(selectedWG(), "selectedWG"); }
}
public void sleep() {
ERXThreadStorage.takeValueForKey(null, "selectedWG"); super.sleep(); }
I have methods in the WorkingGroup EO that access the selectedGroup:
/** * Gets the selected working group. * * @return selected working group for the thread */ public static WorkingGroup wg() { return (WorkingGroup) ERXThreadStorage.valueForKey("selectedWG"); }
/** * Gets the working group as a local instance in the given context. * * @param ec * editing context to pull a local copy of the user into * @return user instance in the given editing context */ public static WorkingGroup wg(EOEditingContext ec) { WorkingGroup wg = wg(); if (wg != null && wg.editingContext() != ec) { EOEditingContext currentWGEc = wg.editingContext(); currentWGEc.lock(); try { WorkingGroup localWG = (WorkingGroup) ERXEOControlUtilities.localInstanceOfObject(ec, wg); wg = localWG; } finally { currentWGEc.unlock(); } } return wg; }
Here I use the selected Working Group to determine which Forum to assign a topic to when it is created:
public void init(EOEditingContext ec) { super.init(ec); setTopicDescription("Unspecified Topic Description"); setTimestampCreation(new NSTimestamp()); setCreatedByRelationship(Person.currentUser(ec)); // set the forum for the topic WorkingGroup selectedWG = (WorkingGroup) WorkingGroup.wg(ec); NSArray forums = selectedWG.forums(); Forum aForum = (Forum) forums.lastObject(); setForumRelationship(aForum); }
|