首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 网络技术 > 网络基础 >

逾越边界: 对 Rails 进行扩展 分析 acts_as 插件

2012-08-25 
跨越边界: 对 Rails 进行扩展 分析 acts_as 插件简介:?Java? 编程语言一直以来都是一个很出色的“熔炉”,它

跨越边界: 对 Rails 进行扩展 分析 acts_as 插件

简介:?Java? 编程语言一直以来都是一个很出色的“熔炉”,它具有用于集成的丰富和强大的功能 —— 从用于集成企业库的依赖性注入容器,到 Enterprise JavaBeans (EJB) 技术,再到 Eclipse 的组件模型。通过使用大量这样的理念和架构,Java 开发人员率先采用新的方法将完全不同的软件库和组件组合成一个整体。但是 Java 开发人员并没有对优秀的集成技术造成垄断。本文通过审视一个名为?acts_as_state_machine?的流行插件来了解 Ruby on Rails 插件的工作原理。

?

?

在我撰写这篇文章的时候,德克萨斯州和俄克拉荷马州正从一场持久的暴风雪的影响中慢慢缓解过来。司机们又开始出现在马路上,他们不仅仅担心路面上的冰,还害怕其他性急的驾车者。三天的 “冬眠” 之后,我的生活开始慢慢恢复正常。但当从使用 Java 语言转换到使用 Ruby 后,不久,我便体验到了另一种“寒意”。当我使用 Java 项目时,总是可以找到能够解决一些小范围问题的特殊的 Spring 库或 Eclipse 组件。当 Ruby on Rails 刚出现的时候,我经常需要亲自编写它。令人高兴的是,这种“寒意”也开始慢慢消失,这要归功于一种有效的插件架构,很多人使用它来对 Rails 进行扩展。

关于本系列

在?跨越边界系列?文章中,作者 Bruce Tate 提出这样一种观点,即当今的 Java 程序员们可以通过学习其他方法和语言很好地武装自己。自从 Java 技术明显成为所有开发项目最好的选择以来,编程前景已经发生了改变。其他框架影响着 Java 框架的构建方式,从其他语言学到的概念也可以影响 Java 编程。您编写的 Python(或 Ruby、Smalltalk 等语言)代码可以改变编写 Java 代码的方式。

本系列介绍与 Java 开发完全不同的编程概念和技术,但是这些概念和技术也可以直接应用于 Java 开发。在某些情况下,需要集成这些技术来利用它们。在其他情况下,可以直接应用概念。具体的工具并不重要,重要的是其他语言和框架可以影响 Java 社区中的开发人员、框架,甚至是基本方式。

如果您曾经花了些时间研究过 Rails,那么一定会注意到 ActiveRecord 中的?acts_as?命令。尽管 ActiveRecord 与处理持久性有关,您总是希望将行为添加到类中,而不仅仅进行数据库存储和检索。比方说,通过使用?acts_as_tree,可以将类似树的行为添加到具有?parent_id?属性的类中。通过使用 ActiveRecord 模型中的?acts_as_tree,可以动态地添加方法来管理树,比如检索父记录或子记录的方法。在过去一个月里,我可以找到能够解决投票、版本化、Ajax、复合键以及不受基本 Rails 支持的所有特性的插件。

Rails 中的扩展模型是使用 Ruby 语言构建在特性之上的,与使用 Java 语言构建的模型完全不同。在本文中,我将剖析?acts_as?插件,您可以了解扩展模型的内部。我没有构建端对端场景,而是提供了部分产品示例以涵盖更多方面,并使您认识真实的插件以及如何在真正的生产代码中使用它们。

状态机 API

正如很多人所了解的那样,状态机?是一种关于系统状态的数学表达式。状态机混合了表示状态的节点以及节点间的转换。在任何一个给定的时间,状态机具有一个活动状态,也称为当前状态事件?触发状态之间的转换。为解释这个概念,我将展示我当前工作的一个组成部分:开发和维护 ChangingThePresent.org (CTP),这是一个非盈利性组织和捐赠者的平台(参见?参考资料)。CTP 让非盈利性组织可以提交关于其组织的信息和一些捐赠品(例如癌症研究员的一小时义诊时间或者捐赠给一名学生的书本),这就 使捐赠者仅使用一辆购物车就可将其慈善捐赠作为礼物转到他人的名下。收集所有这些信息会导致逻辑问题,所以我选择使用状态机来简化工作流程。

要解决这个问题,我使用了第三方插件,由 Scott Barron 编写,名为?acts_as_state_machine(参见?参考资料)。像很多 Rails 插件一样,acts_as_state_machine?结合使用了 Ruby 的功能和 Rails 专有的特性,不仅提供了一个库,还提供了特定于域的语言 (DSL),从而为用户提供了良好的体验。

一个用户向 CTP 提交内容(submitted?状态)。然后 CTP 管理员接收该内容并进行编辑(processing?状态)。如果 CTP 进行内容编辑,非盈利组织应该允许这些更改(nonprofit_reviewing?状态)。当 CTP 或非盈利性组织接受这些内容时,CTP 就会将这些内容显示在站点上(accepted?状态)。图 1 显示了状态机的图形表示:


图 1. CTP 状态机
逾越边界: 对 Rails 进行扩展 分析 acts_as 插件?

使用这个插件,我可以直接对我的类对象进行装饰,使用 DSL 表示不同的状态,在状态之间进行转换,而且事件会触发这些转换。清单 1 显示了我用来在 CTP 中管理非盈利组织的状态机的简化版本:


清单 1. 示例状态机

?

Acts_as plug-ins

原则上讲,所有的?acts_as?插件工作原理相同。始终执行下面的步骤构建一个?acts_as?模块:

  1. 创建一个模块。以?acts_as_?作为名字的开头。
  2. 在某些初始化代码中,打开?ActiveRecord?基类并添加?acts_as_?模块。
  3. 在?acts_as_?函数(比如?acts_as_state_machine)中扩展目标类的行为。

快速浏览一下 init.rb 中的初始化代码,如清单 3 所示:


清单 3. acts_as_state_machine 的初始化代码

?

初始化模块

现在,我将避开实现状态机的具体细节,将主要介绍状态机与插件的接口。清单 4 显示了模块定义和状态机本身的接口:


清单 4. 模块结构

?

Acts_as 模块

回顾一下插件制作者需要的三个条件:放置实现的位置,公开 DSL(类方法)的方法以及为状态机公开实例方法的方法。这些包括清单 3?中起作用的事件方法。清单 4?提供了放置实现的位置。下一个代码片段将处理 DSL。

acts_as?插件架构具有一个定位点:acts_as?宏。?acts_as?插件的客户机将通过方法调用将这个方法引入到目标类中。在本文的示例中,我调用了?清单 1?中?Nonprofit?类的?acts_as,使用了下面的代码:

?

添加类和实例方法

在清单 6 中,终于看到了魔术般地引入了 DSL:


清单 6. acts_as_state_machine 的类方法

?

结束语

您可能会想,仅仅构建一个状态机并将它当作库来使用岂不更加简单。与之相比,acts_as?插件更加好用。它使您可以有效地将一个状态机列添加到数据库中。其他插件则可以让您完成版本化、构建审计记录、处理图像以及执行大量其他的简单任务,就如同这些任务是 Rails 环境和数据库间的无缝集成一样。

您可能使用过 Java 语言来将 Eclipse 插件、Ant 任务或者 Spring 库集成到您的代码库中,或者使用过 Java 语言引入 EJB 组件。Java 社区的很多理念改变了开发人员对扩展的认识。这篇有关 Rails 的?acts_as?插件的简短介绍展示了一种新的认识方法。Ruby 语言的灵活性改变了我对扩展的认识。acts_as?插件允许新一代开发人员尝试自己编写扩展,这将为 Rails 带来新的扩展浪潮,通过面向方面编程或字节码增强,很多这种技术也可为 Java 开发人员所用。

下一次,我将就使用 Ruby 与利用我在 Java 平台方面的经验解决棘手问题进行深入比较,并以此结束本系列。在那之前,请继续跨越边界。

?

热点排行