使用XForms和RubyonRails开发小型门诊管理系统,第2部分

实现患者信息XForm

简介

本系列文章的第 1 部分设计了一个 Web 应用程序,让患者在医生办公室中输入信息。讨论了如何使用 XForms、DB2 pureXML 和 Ruby on Rails 创建这样的应用程序,并对这些技术的用法做了一些实验。本文是第 2 部分,我们开始实现该应用程序。我们将设计第一个 XForm,并建立从表单向 DB2 插入数据的 Ruby on Rails 后端。您将看到如何通过这三种技术在整个应用程序中利用 XML。

先决条件

本文假设读者对 XML 和 Web 应用程序有一定的了解。事先对这三种核心技术,XForms、DB2 pureXML 和 Ruby on Rails 有所涉猎当然很有帮助,不过绝对不是必需的。本文使用了 Mozilla XForms 0.8.0.3 版插件。它为所有 Mozilla 浏览器,如 Firefox,提供了 XForms 运行时支持。另一种有用的 Mozilla 插件是 XForms Buddy,提供了 XForms 调试器。本文使用的是 0.5.6 版。还需要 IBM 的 DB2 数据库服务器。本文使用 DB2 Express-C 9.5 版,支持 Windows®、Linux® 和 UNIX® 系统。此外还需要 Ruby on Rails,本文使用的是 Ruby 1.8.6 和 Rails 1.2.5。还用到了与 Rails 结合使用的 Mongrel Web 服务器。可通过 Ruby Gems 安装(只要在命令行中输入 gem install mongrel 即可)。

患者信息

第 1 部分讨论了所用的 XForms、DB2 pureXML 以及 Ruby on Rails,它们支持在应用程序的前端和后端使用 XML。这种设计的一个好处是将 XML 数据放在了核心位置。XML 数据模型的设计决定了如何实现基于 XForms 的前端,以及如何使用后端的 Ruby on Rails 从 DB2 检索数据。因此,开发应用程序应该首先从设计 XML 数据模型开始。

XML 数据模型

应用程序允许患者输入医生和其他医务人员需要的信息。比如患者的姓名、保险公司、年龄、合作医疗支付额度等,当然还有他们的症状。了解这些之后,清单 1 显示了典型的数据模型实例。

清单 1. 典型的患者信息 XML 实例

<?xml version="1.0" encoding="UTF-8"?><Info><FirstName>John</FirstName><MiddleName>David</MiddleName><LastName>Smith</LastName><Age>33</Age><Insurer>HealthCo</Insurer><Id>555-69-1212</Id><PolicyHolder>true</PolicyHolder><Copay>10</Copay><Symptoms>Cough, Fever</Symptoms></Info>

大部分是简单的字符串,但也有少数例外。中间名应该是可选的字段。年龄是整数,并且必须是非负数。co-pay 同样如此。保单持有者是一个 Boolean 标志。Id 应该定义成固定的范式:三个数字、两个数字、四个数字。清单 2 显示了描述患者数据模型的 XML 模式。

清单 2. 患者模式

<?xml version="1.0" encoding="UTF-8"?><xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"targetNamespace="http://developerworks.ibm.com/patient"xmlns="http://developerworks.ibm.com/patient"elementFormDefault="qualified"xmlns:this="http://developerworks.ibm.com/patient"><xs:simpleType name="policyId"><xs:restriction base="xs:string"><xs:pattern value="[0-9]{3}-[0-9]{2}-[0-9]{4}"/></xs:restriction></xs:simpleType><xs:element name="Info"><xs:complexType><xs:sequence><xs:element name="FirstName" type="xs:NMTOKENS"/><xs:element name="MiddleName" type="xs:NMTOKEN" minOccurs="0"/><xs:element name="LastName" type="xs:NMTOKENS"/><xs:element name="Age" type="xs:nonNegativeInteger"/><xs:element name="Insurer" type="xs:NMTOKENS"/><xs:element name="Id" type="this:policyId" /><xs:element name="PolicyHolder" type="xs:boolean"/><xs:element name="Copay" type="xs:nonNegativeInteger"/><xs:element name="Symptoms" type="xs:string"/></xs:sequence></xs:complexType></xs:element></xs:schema>

定义了 XML 数据模型之后,现在可以编写允许用户建立数据模型实例的 XForms 了。

患者 XForms

现在我们知道了需要患者输入应用程序的数据。定义 XForms 就非常简单了。只要建立和数据模型中元素相对应的表单元素就行了。每个表单元素的类型取决于数据元素的数据类型。患者信息的 XForms 如清单 3 所示。

清单 3. 患者信息 XForms

<?xml version="1.0" encoding="ISO-8859-1" ?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"xmlns:xf="http://www.w3.org/2002/xforms"><head><meta. http-equiv="Content-Type"content="text/html; charset=ISO-8859-1" /><title>Patient Information</title><xf:model><xf:instance><Info xmlns=""><FirstName/><MiddleName/><LastName/><Age/><Insurer/><Id/><PolicyHolder/><Copay/><Symptoms/></Info></xf:instance><xf:submission action="http://localhost:3000/kiosk/create"method="post" id="submit-info"/></xf:model></head><body><p><div id="firstName"><xf:input ref="FirstName"><xf:label>First Name:</xf:label></xf:input></div><div id="middleName"><xf:input ref="MiddleName"><xf:label>Middle Name:</xf:label></xf:input></div><div id="lastName"><xf:input ref="LastName"><xf:label>Last Name:</xf:label></xf:input></div><div id="age"><xf:input ref="Age"><xf:label>Age:</xf:label></xf:input></div><div id="insurer"><xf:input ref="Insurer"><xf:label>Name of Insurance Provider:</xf:label></xf:input></div><div id="idNumber"><xf:input ref="Id"><xf:label>Insurance ID Number(###-##-####):</xf:label></xf:input></div><div id="holder"><xf:select1 ref="PolicyHolder"><xf:label>Are you the policy holder?</xf:label><xf:item><xf:label>Yes</xf:label><xf:value>true</xf:value></xf:item><xf:item><xf:label>No</xf:label><xf:value>false</xf:value></xf:item></xf:select1></div><div id="copay"><xf:input ref="Copay"><xf:label>Co-pay :$</xf:label></xf:input></div><div id="symptoms"><xf:textarea ref="Symptoms"><xf:label>Please describe your symptoms:</xf:label></xf:textarea></div><div id="submit"><xf:submit submission="submit-info"><xf:label>Submit Information</xf:label></xf:submit></div></p><a href="kiosk/list">Back to List</a></body></html>

下面对 清单 3 中的 XForms 简单介绍一下。它有一个模型和一个实例。实例是前面定义的患者信息数据模型的空白版本。提交是模型的一部分。提交将把模型实例传递给提交动作属性中指定的 URL。表单体包含一系列的 XForms 元素。每个元素都使用 ref XPath 绑定到模型实例。无论用户在表单中输入什么数据,都将绑定到模型实例。在浏览器中打开 XForms 将看到类似图 1 所示的结果。

图 1. 患者 XForms

虽然不够完美,但确实是一个具备所需功能的 XForm。有几点需要注意:

.

首先,这是一个 XHTML 页面,而不是通常的 HTML 页面。如果将页面扩展名改为 .html 或者 .htm,就无法正确地呈现。这是因为 XForms 要求使用 XHTML,因此 Mozilla 插件对 HTML 页面不起作用。

其次,由于是 XHTML,因此仍然支持 CSS。这是改变页面外观的最简单方式。很快将使用 CSS 作为数据验证的一部分。

最后,还要注意 URL http://localhost:3000/patient.xhtml。上例中的页面由 Mongrel Web 服务器上的 Ruby on Rails 应用程序提供。该页面是静态的,因此只需要将其复制到 Rails 应用程序的 public 目录。也可使用默认的 WEBrick Web 服务器,但是需要额外配置才能支持 XHTML 页面。而 Mongrel 不需要额外的配置就能支持 XHTML 页面。

如前所述,提交表单将触发模型实例的 POST。但是在处理 post 之前需要进行某些验证。

验证

数据输入最常见的任务之一就是检查输入的数据。通常最好在客户机完成,以免把无效的数据提交到系统后端。一般来说,这需要编写 JavaScript. 提取数据然后执行某些规则(也许是正则表达式)。幸运的是 XForms 在这方面做了很多简化。XForms 使用的是 XML,XML: XML schema 定义了完善的数据验证语法。使用前面 清单 2 定义的模式为新建的 XForms 添加验证,如清单 4 所示。

清单 4. 带有验证模式的 XForms 模型

  <title>Patient Information</title><style. type="text/css">@namespace xf url("http://www.w3.org/2002/xforms");xf|input {display: table-row;line-height: 2em;}xf|label {display: table-cell;text-align: right;font-family: Ariel, Helvetica, sans-serif;font-weight: bold;font-size: small;padding-right: 5px;width: 250px;}xf|*{display: table-row;line-height: 2em;}#submitLabel{display: table-row;}*:required {background-color: yellow;}*:invalid {background-color: yellow;}</style><xf:model id="patientModel" schema="patient.xsd"><xf:instance xmlns="" id="patient"><p:Info><FirstName></FirstName><MiddleName></MiddleName><LastName></LastName><Age></Age><Insurer></Insurer><Id></Id><PolicyHolder></PolicyHolder><Copay></Copay><Symptoms></Symptoms></p:Info></xf:instance><xf:submission action="http://localhost:3000/kiosk/create"method="post"id="submit-info"/></xf:model>

请注意,模型引用了一个模式(patient.xsd)。XForms 会自动加载该模型并进行验证。此外还增加了一些 CSS 显示无效的数据。在浏览器中打开的结果如图 2 所示。

图 2. 包含验证和 CSS 的 XForms

用户必须输入必要的字段才能提交表单。如果输入的数据有效,将自动改变颜色并将焦点转移到新的表单字段。想一想,如果使用 JavaScript. 需要编写多少代码。但利用 XSD 再加上一些 CSS 就轻松完成了。

XForms 提供了多种数据验证方式。不一定要使用 XML 模式,但这确实是一种简单的办法,尤其是对于很容易用模式描述的数据。客户端验证就绪之后,可以在服务器端集中处理提交的数据了。

表单提交

您可能已经注意到为表单提交定义了一个 URL。如果熟悉 Ruby on Rails,对这个 URL 应该不陌生。约定优于配置,因此遵循 Rails 的约定,URL /patient/create 对应 patient 控制器的 create 动作。使用 Ruby 生成脚本可以很容易实现,如清单 5 所示。

清单 5. 生成患者 scaffolding

>ruby script/generate scaffold patient kioskexists app/controllers/exists app/helpers/create app/views/kioskexists app/views/layouts/exists test/functional/dependency modelexists app/models/exists test/unit/exists test/fixtures/skip app/models/patient.rbidentical test/unit/patient_test.rbidentical test/fixtures/patients.ymlcreate app/views/kiosk/_form.rhtmlcreate app/views/kiosk/list.rhtmlcreate app/views/kiosk/show.rhtmlcreate app/views/kiosk/new.rhtmlcreate app/views/kiosk/edit.rhtmlcreate app/controllers/kiosk_controller.rbcreate test/functional/kiosk_controller_test.rbcreate app/helpers/kiosk_helper.rbcreate app/views/layouts/kiosk.rhtmlidentical public/stylesheets/scaffold.css

生成的东西有些不需要。可以删除没有用的文件。最重要的两个是 patient 和 kiosk_controller 类。kiosk_controller 类,您可能已经猜到,是用于处理 XForms 请求的控制器。现在看看如何修改模型和控制器以便保存来自 XForms 的 XML。

Rails 模型和控制器

使用 Rails scaffolding 可以加快应用程序的开发。很多 Rails 应用程序中,不需要修改控制器,就可以直接使用 scaffolding 处理和数据库的交互。通过利用 Rails ActiveRecord 类的对象-关系映射代码,这是可以实现的,该类是所有模型的基类(包括 patient 类)。ActiveRecord 最初并非用于处理 XML,因此需要修改生成的类。首先看看清单 6 所示的 patient 类。

清单 6. 默认的 patient 类

class Patient < ActiveRecord::Baseend

可以看到,默认情况下 Patient 类仅仅扩展了 ActiveRecord。ActiveRecord 根据映射的数据库表的列名动态创建访问器。它有一个构造函数接受名称/值对作为参数。应用程序控制器利用它直接传入表单数据。利用这一点我们来修改 patient 类,如清单 7 所示。

清单 7. 修改后的 patient 类

require 'rexml/document'class Patient < ActiveRecord::Basedef information=(value)self[:information] = value.to_sendend

变动不大,但是很重要。我们希望在内部用字符串保存信息,这样在 ActiveRecord 将信息插入数据库的时候就能序列化为字符串。但是传递给模型的时候呢?由控制器来完成。清单 8 显示了默认的控制器。

清单 8. 默认的 Kiosk 控制器

class KioskController < ApplicationControllerdef indexlistrender :action => 'list'end# GETs should be safe (see http://www.w3.org/2001/tag/doc/whenToUseGet.html)verify :method => :post, :only => [ :destroy, :create, :update ],:redirect_to => { :action => :list }def list@patient_pages, @patients = paginate :patients, :per_page => 10enddef show@patient = Patient.find(params[:id])enddef new@patient = Patient.newenddef create@patient = Patient.new(params[:patient])if @patient.saveflash[:notice] = 'Patient was successfully created.'redirect_to :action => 'list'elserender :action => 'new'endenddef edit@patient = Patient.find(params[:id])enddef update@patient = Patient.find(params[:id])if @patient.update_attributes(params[:patient])flash[:notice] = 'Patient was successfully updated.'redirect_to :action => 'show', :id => @patientelserender :action => 'edit'endenddef destroyPatient.find(params[:id]).destroyredirect_to :action => 'list'endend

前面已经把 XForms 的动作 URL 定义为 /kiosk/create,因此将调用上面的 create 方法。Rails 认为提交的时候获取的是一系列 HTML 表单元素而不是 XML 文档。因此需要修改这个方法以便解析 XForms 发送的 XML 文档。清单 9 显示了修改后的 create 方法。

清单 9. 修改后的 create 方法

 def createdoc = REXML::Document.new("<Info></Info>")params[:Info].each_pair do |key,value|if (key.index(':') == nil) #namespace attributesel = REXML::Element.new keyel.add_text valuedoc.root.add elelsedoc.root.add_attribute key,valueendend@patient = Patient.new@patient.information = docif @patient.saveflash[:notice] = 'Patient was successfully created.'redirect_to :action => 'list'elserender :action => 'new'endend

首先要注意,这里使用 REXML 创建 XML 文档。REXML 是 Ruby 提供的一个标准库。XForms 通过 Info 参数传递的 XML 文档作为一个对象来解析。只需要迭代遍历再转换回 XML 即可。这样就可以让 Rails 把文档插入数据库。现在可以测试一下。

测试应用程序

测试应用程序只需要使用一般的 ruby script/server start 命令启动服务器。然后在浏览器中打开 XForms,如 图 2 所示。填写表单并单击 Submit Information。结果如图 3 所示。

图 3. 患者名单

这个 UI 是怎么来的?这是 Rails scaffolding 提供的标准列表 UI。请注意,它使用一些非格式化的 XML 显示 Info 字段。向右滚动可以看到查看、编辑和删除患者的控件。查看和删除都没有问题!但是编辑不行,页面下方的 New Patient 链接也不行。必须让这些链接指向 XForms,我们需要从这里输入数据。这是本系列第 3 部分要解决的内容!

结束语

本文介绍了如何使用 XForms 创建数据输入表单让患者输入自己的信息。XForms 负责将患者数据绑定到 XML 文档,甚至能够按照 XML 模式验证数据。应用程序将 XML 文档提交给 Ruby on Rails 控制器。Ruby 很容易地将输入解析为 XML 并将其序列化为字符串。DB2 理解序列化的 XML 字符串,使用 pureXML 技术存储它。甚至不需要进行额外的工作,Rails 就能够显示这些数据。接下来,可以使用 DB2 XML/SQL 语法查询 XML 数据和检索,使用 Ruby 导航和提取数据。

本文配套源码

效果只能是既费时又没有胜利,再聪慧的人也没法成学。

使用XForms和RubyonRails开发小型门诊管理系统,第2部分

相关文章:

你感兴趣的文章:

标签云: