WebObjects on Rails
WebObjects on Rails
- Subject: WebObjects on Rails
- From: "Pierce T. Wetter III" <email@hidden>
- Date: Wed, 26 Apr 2006 16:58:03 -0700
(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 (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden