WebObjects on Rails
Pierce T Wetter shared a nice trick on global
page direct actions with url query parameters. Nice tip
Pierce!
Read More....
Copied directly and unaltered from Pierce's
email to the developer
list:
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.
Posted: Thursday - April 27, 2006 at 09:02 AM