跳转到内容

WebObjects/替代技术/Ruby on Rails

来自 Wikibooks,开放世界中的开放书籍
(从 Programming:WebObjects/Alternative Technologies/Ruby on Rails 重定向)

Pierce T. Wetter III

[编辑 | 编辑源代码]
神话:WebObjects 难以与 Ajax 一起使用。
[编辑 | 编辑源代码]

现实:如果您能获得文档,WebObjects 与 Ajax 一起使用起来相对容易,只是只知道一个用于 Ajax-WO 支持的库,而且它没有得到很好的记录。即使这样,该库也只走到了这一步,因为它只是提供了一些新的组件来包装一些 script.aculo.us 标签。

此外,WO 文档总是错误地将人们推向组件操作,而不是直接操作。

[也就是说,如果您避免了 WO 的大部分功能,并且不使用组件操作,ajax 会更容易。如果您确实使用组件操作——而我还没有参与过一个不使用它的项目——那么 ajax 使用似乎会像下面描述的那样,吹掉您的页面缓存。所以,在 WO 中使用 AJAX 真的非常容易。真的很容易。只是它不起作用。]

[mschrag:虽然我同意上面评论者关于组件操作在 WO 中提供了大量功能的说法,但 AJAX 和组件操作并不冲突的说法是不正确的。Project Wonder 的 Ajax 组件 直接解决了在不影响页面缓存的情况下将组件操作与 Ajax 一起使用的方法。虽然 Wonder 内部这些功能的实现并不简单,但它证明了这确实是可以实现的,如果您使用 PW 组件以及 ERXSession,您将免费获得此功能。]

神话:您无法在 WebObjects 中为标签分配名称或 ID 值。
[编辑 | 编辑源代码]

我明确地提到了这一点,因为最近有人问我这个问题,因为他们试图将一个 WYSIWYG JavaScript 编辑器分配给一个文本区域。

现实:实际上,真正发生的是,如果您在 WebObjects 中没有为您的 TextArea 指定 name=value 或 id=value 行,它会为您生成一个唯一的行。但是,您完全可以在您的 .wod 文件中指定一个,WO 会使用它。然后,由您来确保它是唯一的,这样您就不会有多个具有相同名称的文本区域标签。换句话说,如果您只有一个希望附加 JavaScript WYSIWYG 编辑器的文本区域,只需添加

 textarea: WOText
 {
   id='wysiwyg';
   name='wysiwyg';
   value=textValue;
 }

在您的 .wod 文件中,您可以使用 ID 很好地使用您的 JavaScript。

神话:WebObjects 生成 HTML
[编辑 | 编辑源代码]

现实:仅仅因为您的 .wo 文件的组件是 .html 和 .wod,并不意味着 WebObjects 只能生成 HTML。WebObjects 的本质上是一个非常、非常、非常复杂的 printf。组件的结果可以是 HTML、XML、JavaScript,甚至二进制数据。您实际上可以在 .HTML 中放入任何您想要的内容,并将 WebObjects 当作一个巨大的合并引擎。例如,您可以使用 WebObjects 生成 PDF 文件;它们只是文本,您可以很容易地将文本替换到 PDF 模板的中间。

[我把这个假设留在这里,但我考虑删除它,因为没有人关心 WO 能够生成一个乱七八糟的 pdf 文件。人们关心的是像 GWT 这样的 JavaScript 代码生成,而 WO 确实无法做到这一点。]

所以,我做的第一件事是,我听说 Rails 很酷,而且让 Ajax 很容易。我以前也听说过,但那是当版本号为 0.13 的时候……所以我出去买了 Rails 书,你知道我发现了什么吗?

并不是 Rails 在 Ajax 上很牛,而是 Prototype Javascript 库很牛。文档中大肆宣传用一行代码来做 Ajax。

  <div id='<= posting.id'>
    <%= link_to_remote  [div to update] [link options] -> %>
  </div>

现实情况是,Rails 所做的只是写了一行 JavaScript。从我添加到应用程序中的 Ajaxy “评分”代码来看,请看以下内容

  <div id='<WEBOBJECT name=postingID></WEBBOBJECT>'>
    <a href="#" onclick="new Ajax.Updater('<WEBOBJECT name=postingID></WEBBOBJECT>', '<WEBOBJECT name=ratePosting></WEBOBJECT>', {asynchronous:true, evalScripts:true}); return false;">1</a>
  </div>

好的,让我们分解一下。Ajax.Updater 从 Prototype 库的工作方式是,您为它提供一个 DOM 对象的 ID 和一个 URL,它将使用 URL 的内容替换具有该 ID 的 DOM 对象。通常,您使用一个 div 标签指定要更新的区域,我出于完整性而显示了它。对于评分,我需要 1 个 div 标签来包含所有 5 个评分星

<a></a><a></a><a></a><a></a><a></a>

. 我也会使用 WOGenericContainer 来生成具有正确 ID 的 div 标签,而不是使用 id='<WEBOBJECT name=postingID></WEBBOBJECT>' 行,但我希望它很明显是 div 标签。

所以 Ajaxy 部分是 <a> 标签,而不是 div 标签。

这里我有一个手动构建的 <a> 标签,带有一段 onclick javascript 代码。它对 Prototype 库进行了一次调用,该库具有以下很酷的调用

 new Ajax.Updater( elementid, url, options)

它做的事情非常简单:它从指定的 URL 中提取 HTML,并将具有指定 ID 的元素替换为下载的 HTML。

两个 WebObjects 标签指定了元素 ID 和链接,它们只是一个 WOString 和一个 WOActionURL

 postingID: WOString { currentPosting.primaryKeyString; }
 ratePosting: WOActionURL { see discussion }

现在就我而言,我是一个直接操作狂。所以我的 WOActionURL 看起来像这样

 ratePosting :WOActionURL
 {
   directActionName="PostingRater";
   ?pkey=currentPosting.primaryKey;
   ?rating=cRating;
   ?wosid=NO;
 }

这会产生与 Rails 类似的结果,因为在 rails 中,您必须为每类链接定义一个操作。就我而言,我将 directactions 与页面/组件绑定在一起,所以我的 “PostingRater” 页面将返回与现有 <div> 定义匹配的组件级 HTML(减去任何 HEAD/BODY 标签)。由于我们使用的是 WebObjects,如果我们使用一个组件构建包含的 <div> 标签,这将非常容易,PostingRater 可以像这样

 <WEBOBJECT name=RatingDiv></WEBOBJECT>

使用组件操作,它可以更简单

 ratePosting: WOActionURL { action=ratePosting;}

因为 WebObjects 不同于 Rails,它可以具有有状态组件,RatingDiv 组件实际上可以拥有所有逻辑,并将其自身作为操作的结果返回

 public WOReponse ratePosting
 {
   currentPosting.ratePosting(currentRating);
   return self; // since this is called from JavaScript
                    // return just myself, not self.page
                    // this will tell WO to render only
                    // this as a result.
 }

也就是说,javascript 的链接将进入 RatingDiv 组件,其中包含所有已设置好的内容:当前帖子、当前评分。然后返回 self 会导致 div 重新生成。

但是,这里有一个问题,因为从 javascript 调用的组件操作会算作您的回溯计数。由于某人可能会向下浏览页面,点击一个又一个评分,这可能是一个问题。如果您的最大回溯计数为 10,而您在一个页面上有 20 个帖子,那么他们将无法对第 11 个页面进行评分。

所以,Rails 有一行代码,我只有两行 WOTags,但这些代码可以(也应该)通过创建 WODynamicElement 来直接生成链接而轻松地组合在一起。本质上,创建一个 “RemoteLink” WODynamicElement 来完成 Rails “link_to_remote” 调用所做的一切会非常容易,即获取要更新的 ID 以及 WOActionURL 接受的所有选项。

但此外,WebObjects 的解决方案在许多方面优于 Rails 的解决方案。Rails 支持 “部分页面” 和 “组件”,但现实情况是,组件非常繁重/缓慢,而部分页面无法完全满足您的预期。所以,WebObjects 的解决方案通过将逻辑和状态都包装在一个组件中,最终比典型的 Rails 解决方案更 DRY(不要重复自己)并且封装得更好。在您想要 Ajax 位的页面中,您指定了组件,并将 ajax 处理逻辑放在组件本身中。

我还没有在 Rails Ajax 支持中看到任何无法通过 WOComponents 和 WODynamicElements 的组合在 WO 中轻松完成的东西。Rail “Ajax 支持” 中几乎所有内容都是 Prototype 中的一行代码。事实上,由于页面/组件可以具有状态,所以在 WO 中完成它可能比在其他系统中更_容易_。此外,我认为您可以构建一套 WOComponents,它们提供比 Rails 更_优越_的 Ajax 支持。只是没有人编写支持的 WODynamicElements 或 WOComponents。

现在,看一下 Ahmet 的 dojo Hello World 示例,我不得不说,在 WebObjects 中没有任何东西可以阻止这样做。本教程的 90% 是与任何特定技术无关的 JavaScript。与 PHP/ASP/ColdFusion 特定的部分定义了一个新页面,就像您在 WebObjects 中需要做的那样。只需在 JavaScript 中使用 WOActionURL 替换 url: 即可。

我还认为,从这个例子来看,dojo 作为 JavaScript 工具包有点弱。与 Prototype 相比,您将在 Dojo 中花费大量时间来连接 JavaScript 代码。或者将 dojo 与 Yahoo UI 库进行对比

http://developer.yahoo.com/yui/

yui 中的整个 “Dialog” 东西很酷

http://developer.yahoo.com/yui/container/dialog/index.html

并且非常适合 WO 从各个部分构建页面的模型。

再说一次,dojo 现在还只有 0.3 版本。WYSIWYG 编辑器很不错,但我真的不想用另一种标签语言来定义我的对话框。HTML 对我来说已经足够了。

那么,你在使用 dojo/wo 时到底遇到了什么问题?请考虑一下,问题可能出在 dojo 上,而不是 WO 本身。你可以轻松地为每个新的 dojo 标签创建一个 WODynamicElement,将它们收集到组件中,这样比直接使用 dojo 会容易得多。

华夏公益教科书