(If you received this twice, that's because I just found out there are TWO WO mailing lists, one at Apple and one at OmniGroup and sent it to both)

The Ruby On Rails book has inspired me to share some of the tricks I've learned over the years to make WebObjects more streamlined.

Let's start with the following:

public class EZDirectAction extends DirectAction {

        public EZDirectAction(WORequest aRequest) {
                super(aRequest);
        }

        public WOActionResults performActionNamed(String name) {
                EZPage nextPage=(EZPage) pageWithName(name);
                nextPage.takeFormValues(request().formValues());

                return nextPage;
        }
}

public class EZPage extends EZComponent {

// better solution is actually to have EZComponent implement the
// EOKeyValueCodingAdditions protocol, then this is one line
// self.takeValuesFromDictionary(values)

        public void takeFormValues(NSDictionary values) {

        java.util.Enumeration enum=values.getValueList().objectEnumerator();
        while (enum.hasMoreElements()) {
                String key=(String) enum.nextElement();

                Object obj= values.valueForKey(key);
                if (obj != null) {
                        self.takeValueForKey(obj,key);
                }
        }
}

Ok, now this code is making only one assumption, and its a good one:

 a. All your _page_ components are subclasses of EZPage.

What this code does is enable direct actions for every single page in your WO application, _without any additional coding_. All you have to do is add it to the project and your application will automatically understand URLs of the form:

/wa/MyPage?valueS=1&value2S=2

This is doing a bit of voodoo if you're not familiar with the ins and outs of the lower levels of the the WO frameworks, but basically the code does two things.

First, rather then use the default behavior of "performActionNamed", which appends "Action", and then looks for a method of that name, we simply map pages to action on a 1-1 basis (which is what you do 99.9% of the time anyways).

Now WO doesn't really make a distinction between pages and components, but we'll do it here for simple security reasons because we don't necessarily want users to be able to pull up arbitrary bits of the application (even though /wo/Component.wo works in most WO apps anyways). Plus I've always found that pages function as a controller in the MVC paradigm anyways so you end up needing things at the page level you don't need at the component level. So its incredibly useful to have cross-application base classes for both your components and your pages.

Then, although its calling "form values", what that's really doing is pulling all of the key-labeled strings out of the URL and shoving them into the page using key-value-coding. WOComponent doesn't implement EOKeyValueAdditions, so you can't just shove in the whole dictionary in one line, you have to walk through the dictionary and shove them in one by one instead.

So if "MyPage" above takes two parameters, rather then have to explicitly do any initialization in the direct action, what I instead do is write a method like the following:

public class MyPage extends EZPage {

   public void setValueS(String s)
   {
        self.setValue(s.toInteger())
   }
}

That is, what happens is that all values in URLs are string, rather then integers, or whatever. So if you have string parameters, you're done, but if you have non-string parameters, you have to convert them as part of the key-value-coding process.

If your page is tied to an EO object its not much more complicated:


   public void setKeyS(String s)
   {
        self.setValue(EOUtilities.objectWithPrimaryKeyValue(
                self.session().defaultEditingContext(),
                "MyObject",s.toInteger())
   }

In fact, if you like, you can sometimes put that code in your page baseclass
so that its only in one place. Or perhaps all the pages that can inspect
a particular type of object will have a superclass with that method.

Ok, not much code, and the payoff is that now you can write links as follows:

link: WOHyperlink
{
   directActionName: "MyPage";
   ?value1S=value1;  // URL generation converts value[12] to a string
   ?value2S=value2;
   ?keyS=object.key; // grab the primary key
   ?wosid=NO; //assuming you're using cookies
}

Which means you no longer have to craft an action for 99% of the links on your site, because most of the time you're just going to just going to link to a specific object. And your links will be bookmarkable, etc.

So no more links like this:

https://jobs.apple.com/cgi-bin/WebObjects/Employment.woa/1/wo/ fpzfbEkBBR22HLXV28KMDg/5.34.33.29.3.3.1.1.1

 Ok? :-)

Pierce


_______________________________________________
Do not post admin requests to the list. They will be ignored.
Webobjects-dev mailing list      (Webobjects-dev@lists.apple.com)
Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/webobjects-dev/archive%40mail-archive.com

This email sent to archive@mail-archive.com

Reply via email to