首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

动态类型语言中的 Web 开发策略(1)Ruby模板

动态类型语言中的 Web 开发策略(1)Ruby模板

在 Java Web 开发的早些时候,Sun 和 Microsoft 曾经争夺过有关构建动态 Web 页面的实际标准的控制权。Sun 公司引入了 Servlet API。通过 servlet,您可以用 Java 语言的所有功能快速生成一个 Web 页面。具备编译 servlet 能力的免费 servlet 容器实现 (Apache Tomcat) 的存在使得 servlet 变得非常流行。与之相对的,Microsoft 公司引入了称作 Active Server Pages (ASP) 的 API。该技术很容易:您可以快速掌握并创建更多的高级 Web 页面,其中包括一些具有数据库支持或其他动态内容的页面。
关于本系列在  系列中,作者 Bruce Tate 提出了这样一个观点:如今的 Java 程序员可以通过学习其他方法和语言得到很好的其他思路。自从 Java 技术明显成为所有开发项目的最佳选择以来,编程前景已经改变。其他框架正影响着构建 Java 框架的方式,从其他语言中学到的概念也影响着 Java 编程。您编写的 Python(或 Ruby、或 Smalltalk 等) 代码可以改变您处理 Java 编码的方式。
本系列向您介绍与 Java 开发截然不同但可直接应用于 Java 开发的编程概念和技术。在一些情况下,需要集成该技术以对其进行利用。而在另一些情况下,则可以直接应用这些概念。单独的开发工具并不重要,重要的是这种思想,即能够影响 Java 社区中开发人员、框架,甚至基本方法的其他语言和框架。

首先来说说 JSP 技术。JSP 被设计来直接与 ASP 竞争(顾名思义)。使用 JSP 技术,您可以使用标记构建一个 Web 页面并将 Java 代码直接放入页面中。JSP 容器将 JSP 文件编译成 servlet 形式。然后 servlet 引擎像执行其他 servlet 一样执行该页面。JSP 和 ASP 一样,都实现了一个基于模板的方式。模板可以像您想要在用户浏览器中所呈现的那样,帮助您构建一个简单的 Web 页面。当模板引擎处理简单的占位符元素时,您可以用值、组件或作为页面一部分的结构来替换这些元素。尽管 Java 平台拥有众多具有通用目的的模板引擎,但 JSP 已经占领了绝对的市场份额,部分原因在于大量 ASP 开发人员转换来使用 JSP。
比起 Java 语言或 ASP,一些其他的语言在处理 Web 开发方面表现要强得多。了解一下动态语言中相互竞争的方法,会让您更加清楚在 Java 平台上能够使用哪些方法。在本文中,我讨论了 Ruby 中代码生成是如何工作的,并且深入讲解了 Seaside 中一种更加根本的基于组件的方法。
Ruby 模板Ruby 模板依赖此语言的简单功能来为 Web 开发提供一种简单却行之有效的方法。通过掌握一些层次化的概念即可快速理解 Ruby 模板,这些概念每一层要比其上一层更加强大。
Ruby 模板最基础的部分是 String。Ruby 字符串是一级对象。当您在 Ruby 中创建一个字符串时,您既能用单引号,也能用双引号把它括起来。清单 1 展示了一些例子,即您可在 Ruby 解释器中键入来创建字符串的三条不同命令:
清单 1. 创建一个 Ruby 字符串
1
2
3
4
5
6
irb(main):001:0> "This is a string.".class
=> String
irb(main):002:0> 'This is also a string.'.class
=> String
irb(main):003:0> String.new('This is yet another string.').class
=> String




Ruby 不处理任何用单引号括起来的字符串信息。如果用双引号括起来,Ruby 会在运行代码的时候进行替换。清单 2 是一个使用换行符的示例。使用单引号时,Ruby 保持换行符不变。使用双引号时,则会解释换行符:
清单 2. 单引号与双引号的比较
1
2
3
4
5
6
7
irb(main):004:0> puts 'Use \n to specify a new line in Ruby.'
Use \n to specify a new line in Ruby.
=> nil
irb(main):005:0> puts "A \\n causes a line break \n like this."
A \n will cause a line break
like this.
=> nil




在第二个 puts 语句中(puts 代表 put string),Ruby 处理了两次替换。单个 \ 后跟一个字符表示不在键盘上的特殊字符,如 \n 代表换行。正如反斜号本身有特殊的意义一样,在一个字符前的 \ 也有着特殊的意义,即转义该字符,这同在 Java 语言中一致。清单 2 处理了 \\ 和 \n 两个替换。  
#{any_expression} 是一个更有趣的替换命令。如果您使用双引号将含有此命令的 String 括起来,Ruby 将返回此字符串,用 any_expression 的值取代 #{any_expression}。清单 3 给出了一个例子:
清单 3. 简单变量替换
1
2
3
4
5
irb(main):006:0> name = "Elvis"
=> "Elvis"
irb(main):007:0> puts "Your name is #{name}"
Your name is Elvis
=> nil




您已经做好了创建一个基本的模板所需的绝大部分准备。只差一步即可完成简单的模板处理。您可以通过在具有单引号的字符串中使用 #{} 替换来推迟赋值。稍后,通过给模板加双引号并调用 eval() 方法,您可以随时将模板与变量绑定,如清单 4 所示:
清单 4.推迟赋值
1
2
3
4
5
6
7
8
irb(main):008:0> template = 'Your name is #{name}'
=> "Your name is \#{name}"
irb(main):009:0> name = gets
Elvis
=> "Elvis\n"
irb(main):011:0> puts eval('"' + template + '"')
Your name is Elvis
=> nil




注意,template 在初始化 name 前就已经存在了。您可以使用这个简单的模板策略来处理非常简单的 Web 页面,但通常您还需要用到更多知识。包含简单编码结构(如含有动态数据的表循环)的能力形成了大多数动态 Web 页面的主干。
用 eRuby 嵌入代码在 HTML 页面中嵌入 Ruby 代码的典型方法(包括在 Rails 中使用的方法)是一个被称作 eRuby 的过滤器。现有的几个实现中包括了一个被称作 ERb 的基于 Ruby 的实现,和一个被称作 eruby(参见 )的速度更快且基于 C 语言的实现。它们每一个都能作为 Web 服务器的插件运行,但在便利地处理本地文件时,您通常会使用 ERb,而当需要更快的速度时,例如对于生产用的 Web 服务器,您会使用 eruby。eRuby 过滤器处理文本文件时,除了下列三种情况以外都会完整地保持原文本:
  • 在 <% 和 %> 之间的文本是 Ruby 代码,eRuby 将如实执行该代码。
  • 在 <%= 和 %> 之间的文本是 Ruby 表达式。eRuby 执行该表达式并用其返回的值替换整个表达式。
  • 一行中以单个 % 开头的内容,将被作为 Ruby 代码执行。
例如在清单 5 中名为 test.rhtml 的文件(按照惯例,.rhtml 是针对 eRuby 标记的、包含有 HTML 的文件的扩展名)。清单 5 使用了 Ruby 代码和表达式。请注意 do 循环体中的文本:
清单 5.一个简单的 rhtml 文件
1
2
3
4
<% 4.times do |i|%>
  <h1>This code is inside the loop.</h1>
  <p>This line is pass number <%= i %> through the loop.</p>
<% end %>




    您可以简单地通过 ERb 运行此代码,如清单 6 所示:
清单 6.用 ERb 处理文件
1
2
3
4
5
6
7
8
9
10
11
12
13
> erb test.rhtml

<h1>This code is inside the loop.</h1>
<p>This line is pass number 0 through the loop.</p>

<h1>This code is inside the loop.</h1>
<p>This line is pass number 1 through the loop.</p>

<h1>This code is inside the loop.</h1>
<p>This line is pass number 2 through the loop.</p>

<h1>This code is inside the loop.</h1>
<p>This line is pass number 3 through the loop.</p>

返回列表