IBM®
跳转到主要内容
    中国 [选择]    使用条款
 
 
Select a scope: Search for:    
    首页    产品    服务与解决方案     支持与下载    个性化服务    
跳转到主要内容

developerWorks 中国  >  XML | Information Management  >

使用 XForms 和 Ruby on Rails 开发小型门诊管理系统,第 3 部分: 实现护士和医生 XForm

developerWorks
文档选项

未显示需要 JavaScript 的文档选项

讨论

样例代码

英文原文

英文原文


级别: 中级

Tyler Anderson (tyleranderson5@yahoo.com), 自由撰稿人, Stexar Corp.

2008 年 7 月 07 日

本系列文章 介绍如何结合使用 XForms、IBM® DB2® pureXML™ 和 Ruby 来简化 Web 应用程序的开发,分为四部分,这是第三部分。本系列文章中将开发一个虚构的应用程序来管理医生办公室中的患者信息。您将看到每种技术的强大功能,同时还将看到如何将其结合起来。第 3 部分将开发护士用的表单来编辑患者数据,学习如何用 Ruby 实现这样的功能。

简介

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

本系列中的其他文章

第 3 部分将进一步细化 Ruby 的用户界面,增加两个新表单来查看和编辑已有的患者:一个 Kiosk 视图编辑患者信息,一个新的 Triage 视图让护士查看、编辑和批准输入的患者数据。输入的数据经护士批准后,患者就可以去看医生了。患者看医生的时候,医生可以查看患者的数据并根据的自己的观察添加数据。第 4 部分介绍医生表单的结构,它允许医生阅读和编辑经过护士批准的任何患者数据,并增加医生诊断的结果。





回页首


先决条件

经常用到的缩写词
  • CSS:级联样式表
  • URL:统一资源定位符
  • 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 即可)。下载链接参见 参考资料 小节。





回页首


编辑已有的患者数据

虽然患者能够向系统输入数据了,但是返回的患者如何更新他们的信息呢?目前只能创建新的患者和查看结果。现在需要开发一个表单来编辑和更新原来的患者信息。





回页首


患者编辑表单

Ruby and Rails 技术资源中心

欢迎访问 Ruby and Rails 技术资源中心,这里整理了和 Ruby 动态语言以及十分流行的开源 Web 开发框架 Ruby on Rails 相关的技术文章、教程和相关资源。

查看和编辑已有数据的功能是任何应用程序都不能缺少的,我们将通过一个新的表单来完成。在 public 目录下创建一个新的 XHTML 文件 editPatient.xhtml,同时将第 2 部分的 patient.xhtml 表单更名为 newPatient.xhtml。新的 editPatient 表单和 newPatient 很相似。清单 1 显示了两者的区别。


清单 1. 创建 editPatient 表单
                
...
 <xf:model id="patientModel">

 <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/update/0"
 method="post"
 id="submit-info"/>

 <xf:submission id="load_data"
 action="http://localhost:3000/kiosk/grab/0"
 method="post"
 replace="instance"
 />
 
 <xf:action ev:event="xforms-ready">
 <xf:dispatch name="xforms-submit" target="load_data"/>
 </xf:action> 

 </xf:model>
...
 <a href="kiosk/list">Back to List</a>
 </body>
</html>

非常简单吧?首先要注意,在 id 为 “submit-info” 的提交元素中修改了动作 URL,指向 Ruby 更新脚本。还增加了一个新的动作元素并由 xforms-ready 事件触发,即当表单加载的时候触发。然后触发的这个动作分派 id 为 “load_data” 的提交元素从新的 grab 视图提取数据。后面我们将看到这个新的视图。





回页首


Kiosk grab 视图和控制器

grab 视图根据引用 URL 的 id 变量查询数据库中的患者记录,对 XML 进行适当地格式化,把数据返回 XForm。实现这个新视图需要在 app\views\kiosk 目录下增加一个新文件 grab.rhtml。定义如下(一行)。

<% @headers["Content-Type"] = "text/xml; charset=utf-8" %><%= @patient.information %>

这里将头部 Content-Type 设置为 text/xml,这是 XForms 处理程序要求的格式。然后直接输出患者信息变量,即 DB2 数据库为该记录定义的 XML。

但是这里还需要编辑 kiosk 布局(app/views/layouts/kiosk.rhtml),其中只剩下一行:<%= yield %>

这样做是为了删除 XForms 处理程序所需要的 XML 数据之前和之后的所有多余标签。下一步是在 kiosk 控制器(app/controller/kiosk_controller.rb)中定义 grab,如清单 2 所示。


清单 2. 在控制器中定义 grab
                
  def grab
 id = @request.env["HTTP_REFERER"].split('=')[1]
 @patient = Patient.find(id)
 end

请注意,代码中包含从引用 URL 抓取的客户 id。这样就克服一个限制:XForms 不能在 POST 请求中提交接收到的 GET 请求变量。因此,如果 URL 是:

http://localhost:3000/editPatient.xhtml?id=60

从数据库中提取的记录的 id 是 60。数据然后传递给 清单 1 定义的 grab 视图,后者传递给 XForms。





回页首


Kiosk 列表视图

然后需要修改列表视图(app/views/kiosk/list.rhtml),为当前列出的患者加上链接,以便转到 editPatient 表单查看和编辑患者。修改后的视图如清单 3 所示。


清单 3. 修改 list 视图
                
<h1>Listing patients</h1>

<table>
 <tr>
 <th><%= "ID" %></th>
 </tr>
 
<% for patient in @patients %>
 <tr>
 <td><%=h patient.id %></td>
 <td><%= "<a href=\"../editPatient.xhtml?id=" +
 patient[:id].to_s + "\">Show/Edit</a>" %></td>
 <td><%= link_to 'Delete', { :action => 'destroy',
 :id => patient },
 :confirm => 'Are you sure?',
 :method => :post %></td>
 </tr>
<% end %>
</table>

...

<br />

<a href="/newPatient.xhtml">New patient</a>

请注意显示的列的变化。这里显示了 ID 列,并且 Show/Edit 链接指向 editPatient 窗体,ID 附加在 URL 后面(因此 grab 视图知道从数据库读取哪一条记录并返回 XForm)。注意下方添加新患者的链接。单击该链接将打开本系列第 2 部分创建的表单。

该表单如图 1 所示。


图 1. 患者列表
患者列表

单击链接就会看到包含已有数据的 editPatient 表单,如图 2 所示。


图 2. 在 editPatient 表单查看已有的数据
在 editPatient 表单查看已有的数据

在这里可以根据需要编辑数据。要注意,提交该表单的时候,按照 清单 1 的定义,执行的是 kiosk/update 脚本而不是 kiosk/create 脚本。还有 URL 中的 id 变量,清单 2 中的 grab 控制器依靠它才知道从数据库获取哪个 id。

选择 Submit Information 按钮之前,应该修改 kiosk 控制器的 update 方法。





回页首


Kiosk update 控制器

需要修改 update 控制器来处理 XForms 提交数据,存储到数据库中替代原来的 XML 数据。修改后的 kiosk 控制器如清单 4 所示。


清单 4. 修改 kiosk 控制器的 update 方法
                
  def update
 doc = REXML::Document.new("<Info></Info>")
 params[:Info].each_pair do |key,value|
 if (key.index(':') == nil) #removes 
 el = REXML::Element.new key
 el.add_text value
 doc.root.add el
 else
 doc.root.add_attribute key,value
 end
 end

 id = @request.env["HTTP_REFERER"].split('=')[1]
 @patient = Patient.find(id)
 @patient.information = doc 
 @patient.update_attributes(params[:patient])
 redirect_to :action => 'list'
 end

注意和 create 控制器的相似性。差别在于如何使用引用 URL 检索原有的患者信息。首先,该方法创建了 XForms 提交数据的 XML 文档,然后从数据库检索已有的患者,用新数据替换已有的 XML 数据并保存到数据库。

这样就行了!对用户界面略加修改就能大大加强应用程序的功能,真是令人吃惊。现在可以查看和更新已有的患者记录了。





回页首


护士审批表单

护士审批表单(triagePatient.xhtml)让护士从完全不同的视图(triage)编辑和审查患者输入的数据。triagePatient 表单允许护士使用 Submit Information 按钮编辑患者信息,使用 Approve 按钮编辑和批准患者信息。但是创建该表单之前,需要为患者表添加一个新的字段。





回页首


修改患者表

患者模式中新增一个 approve 字段,用于确定哪些信息已经经过审核批准,哪些还没有。要修改患者模式请打开 DB2 Control Center,找到 Patients 表,如图 3 所示。


图 3. 修改患者模式
修改患者模式

右键单击 Patient 表,像上图那样单击 Alter。在打开的窗口中单击 Add,输入新的字段信息,如图 4 所示。


图 4. 添加 approved 字段
添加 approved 字段

请注意字段名、数据类型、默认值和 Nullable。连续单击 OK。Control Center 将通知您修改已经成功,可以看到修改后的表模式,如图 5 所示。


图 5. 修改后的患者模式
修改后的患者模式

如果使用 DB2 Control Center,实际上不需要使用命令行工具。

现在可以创建 Triage 视图了。





回页首


Triage 视图和控制器

需要把 triage 视图、控制器以及护士 XForm 的患者模型联系起来。创建新的视图和控制器,请输入清单 5 所示的代码。


清单 5. 创建 triage 视图和控制器
                
ruby script/generate scaffold patient triage
 exists app/controllers/
 exists app/helpers/
 create app/views/triage
 exists app/views/layouts/
 exists test/functional/
 dependency model
 exists app/models/
 exists test/unit/
 exists test/fixtures/
 skip app/models/patient.rb
 identical test/unit/patient_test.rb
 identical test/fixtures/patients.yml
 create app/views/triage/_form.rhtml
 create app/views/triage/list.rhtml
 create app/views/triage/show.rhtml
 create app/views/triage/new.rhtml
 create app/views/triage/edit.rhtml
 create app/controllers/triage_controller.rb
 create test/functional/triage_controller_test.rb
 create app/helpers/triage_helper.rb
 create app/views/layouts/triage.rhtml
 identical public/stylesheets/scaffold.css

现在更新 triage 控制器(app/controllers/triage_controller.rb),定义 grab 并修改 update 控制器,如清单 6 所示。


清单 6. 编辑 triage 控制器
                
  def grab
 id = @request.env["HTTP_REFERER"].split('=')[1]
 @patient = Patient.find(id)
 end

 def update
 doc = REXML::Document.new("<Info></Info>")
 params[:Info].each_pair do |key,value|
 if (key.index(':') == nil) #removes 
 el = REXML::Element.new key
 el.add_text value
 doc.root.add el
 else
 doc.root.add_attribute key,value
 end
 end

 id = @request.env["HTTP_REFERER"].split('=')[1]
 @patient = Patient.find(id)
 @patient.information = doc
 approvedCode = params[:id]
 if approvedCode == "1" then
 @patient.approved = "true"
 end
 @patient.update_attributes(params[:patient])
 redirect_to :action => 'list'
 end

其中的 grab 和 kiosk(如 清单 2 所示)控制器的 grab 相同。update 惟一的不同是使用了数据库新增的 approved 字段。请注意,该字段的值从 ID 字段抓取,因此如果更新该记录的 URL 是 http://localhost:3000/triage/update/1,那么该患者就通过批准了。

最后还需要修改一下 triage 布局(app/view/layouts/triage.rhtml),并按照 kiosk 布局的方式定义(<%= yield %>)。要使 grab 视图正常工作需要做这样的修改。既然说到了 grab 视图,将 grab 视图从 kiosk 视图(app/view/kiosk/grab.rhtml)复制到 triage 视图文件夹(app/view/triage)。这样 grab 视图和控制器就准备好了。

接下来需要修改 patient 类(patient.rb)以便容纳新增的数据库字段。





回页首


Patient

为了在数据库中保存 approved 变量,需要修改 patient 类(app/model/patient.rb),如清单 7 所示。


清单 7. 修改 patient 类
                
class Patient < ActiveRecord::Base
 def information=(value)
 self[:information] = value.to_s
 end
 def approved=(value)
 self[:approved] = value.to_s
 end
end

patient 类修改好后,接下来要修改 list 视图。





回页首


Triage list 视图

这是运行护士表单需要修改的最后一个视图。正确的 list 视图应该允许单击患者的名字来编辑其信息。修改 list 视图(app/view/triage/list.rhtml),如清单 8 所示。


清单 8. 修改 list 视图
                
<h1>Listing patients</h1>

<table>
 <tr>
 <th><%= "First Name" %></th>
 <th><%= "Last Name" %></th>
 <th><%= "Approved" %></th>
 </tr>
 
<% for patient in @patients %>
<% if patient.approved=="false" then %>
 <tr>
 <td><% doc = REXML::Document.new(patient.information) %>
 <%= doc.root.elements["FirstName"] %>
 </td>
 <td>
 <%= doc.root.elements["LastName"] %>
 </td>
 <td><%=h patient.approved %></td>
 <td><%= "<a href=\"../triagePatient.xhtml?id=" +
 patient[:id].to_s + "\">Edit/Approve</a>" %></td>
 <td><%= link_to 'Destroy', { :action => 'Delete', :id => patient },
 :confirm => 'Are you sure?',
 :method => :post %></td>
 </tr>
<% end %>
<% end %>
</table>
...

这里我们学习了从 XML 向列表添加新的列,包括显示患者的姓氏和名字,以及患者的信息是否已经过批准。通过 for 循环之后的 if 语句,可以仅向护士显示信息没有经过批准的患者。这里的关键在于如何从 XML 检索姓和名。首先创建一个新的 XML 文档,传入 XML 信息,然后调用 doc.root.elements["FirstName"] 检索 FirstName 元素。姓也通过同样的方式检索。此外还有 Edit/Approve 链接。单击该链接将打开后面将创建的 triagePatient 表单。

编写 triagePatient 表单之前,先看一看图 6 所示的 triage list 视图。


图 6. triage list 视图
triage list 视图

现在开始创建 triagePatient 表单





回页首


Triage XForm

接受 XForms 提交数据的 Ruby 脚本都已就绪。只需要定义 triagePatient XForm 了。将其命名为 triagePatient.xhtml 并放在 public 文件夹中。如清单 9 所示。


清单 9. triagePatient XForm
                

...
 </p:Info>
 </xf:instance>

 <xf:submission action="http://localhost:3000/triage/update/0"
 method="post"
 id="submit-info"/>

 <xf:submission action="http://localhost:3000/triage/update/1"
 method="post"
 id="approve"/>

 <xf:submission id="load_data"
 action="http://localhost:3000/triage/grab/0"
 method="post"
 replace="instance"
 />
 
 <xf:action ev:event="xforms-ready">
 <xf:dispatch name="xforms-submit" target="load_data"/>
 </xf:action> 
...
 <xf:label>Submit Information</xf:label>
 </xf:submit>
 </div>
 <div id="approve">
 <xf:submit submission="approve">
 <xf:label>Approve</xf:label>
 </xf:submit>
 </div>
 </p>

 <a href="triage/list">Back to List</a>
 </body>
</html>

清单 9 中的表单和 editPatient(清单 1)类似,上面的代码显示了两者的区别。load_data 和 submit-info 提交元素没有变,只不过现在指向了 triage 脚本。还有一个新的提交元素(id 为 “approve”)指向下面的 URL,如 清单 9 所示:

http://localhost:3000/triage/update/1

URL 的 id 是 1,因此将患者记录的 approved 字段设为真,如 清单 5 中的 triage update 控件所示。新的提交按钮 Approve 将触发这个新的提交元素。该 XForm 的执行结果如图 7 所示。


图 7. 在 triagePatient 表单中查看待审批的患者数据
在 triagePatient 表单中查看带审批的患者数据

要将数据库中的 approved 字段设置为真,单击 Approve。这样做的同时也把它从 list 视图中删除,如图 8 所示。


图 8. 审批患者信息
审批患者信息

这样就完成了本文所计划的任务。





回页首


结束语

您的 Ruby、XForms 和 DB2 技能越来越完美了。您掌握了如何结合使用 Ruby 和 XForms,并领略了使用 DB2 及其 Control Center 的乐趣和用户友好性。

第 4 部分将创建医生表单,包括供医生护士按照姓氏查找患者的新表单。






回页首


下载

描述名字大小下载方法
第 3 部分的样例代码part3_doctorsOffice.zip11KBHTTP
关于下载方法的信息


参考资料

学习

获得产品和技术

讨论


关于作者

Tyler Anderson 在 2004 年从 Brigham Young University 毕业并获得计算机科学学士学位,次年 12 月获得计算机工程硕士学位。Tyler 目前是一位自由作家,也是 Backstop Media 的开发人员。




对本文的评价










回页首


Adobe、Adobe 徽标、PostScript 以及 PostScript 徽标是 Adobe Systems Incorporated 在美国和/或其他国家的注册商标或商标。 IBM、IBM 徽标、ibm.com、DB2、developerWorks、Lotus、Rational、Tivoli、WebSphere 和 pureXML 是 IBM Corporation 在美国和/或其他国家的商标。 Java 和所有基于 Java 的商标是 Sun Microsystems, Inc. 在美国和/或其他国家的商标。 Microsoft、Windows 和 Windows 徽标是 Microsoft Corporation 在美国和/或其他国家的商标。 Linux 是 Linus Torvalds 在美国和/或其他国家的商标。 UNIX 是 The Open Group 在美国和其他国家的注册商标。 其他公司、产品或服务名称可能是其他公司的商标或者服务标志。 其他公司、产品或服务的名称可能是其他公司的商标或服务标志。

IBM 公司保留在 developerWorks 网站上发表的内容的著作权。未经IBM公司或原始作者的书面明确许可,请勿转载。如果您希望转载,请通过 提交转载请求表单 联系我们的编辑团队。
    关于 IBM 隐私条约 联系 IBM 使用条款