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

实现医生和患者搜索XForms

简介

到目前为止,我们已经创建了帮助患者和护士管理患者数据的 DB2 数据库和三个 XForms 。通过使用 Ruby on Rails 作为处理接口,患者可以向数据库添加新的记录,并在以后更新信息。因此 护士可以查看并适当地修改这些信息,当患者可以诊治的时候批准输入的数据。

这是本系列的最 后一部分,将为医生创建新的视图和控制器以及该视图的两个新表单。医生通过第一个表单可以查看由患 者输入并经过护士批准的患者记录,并增加诊治过程中的新信息。然后开发一个表单让医生和护士按照姓 氏查找患者信息。

先决条件

本文假设读者基本熟悉 XML 和 Web 应用程序。当然,事先涉 猎过 XForms、DB2 pureXML 和 Ruby on Rails 这三种核心技术很有帮助,但不是必需的。本文使用了 Mozilla XForms 插件 0.8.0.3。它为所有的 Mozilla 浏览器提供了 XForms 运行时支持,如 Firefox。 另一种有用的 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 即可)。

医生访问 XForm

医生 XForm(docTorPatient.xhtml)的目的 是让医生看到和护士在 kiosk 以及 approved 视图中所看到的相同的患者信息。在此基础上,这个 XForm. 还需要让医生输入诊治病人的信息。因此除了少数区别外,docTorPatient 表单和 triagePatient 表单非常类似,如清单 1 所示。将该文件命名为 docTorPatient.xhtml 并保存到 public 文件夹。

清单 1. docTorPatient 表单

...<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><BPressure></BPressure><Notes></Notes></p:Info></xf:instance><xf:submission action="http://localhost:3000/docTor/update/0"method="post"id="submit-info"/><xf:submission id="load_data"action="http://localhost:3000/docTor/grab/0"method="post"replace="instance"/><xf:action ev:event="xforms-ready"><xf:dispatch name="xforms-submit" target="load_data"/></xf:action>...<xf:label>Please describe your symptoms:<br/></xf:label></xf:textarea></div><div id="bloodpressure"><xf:input ref="BPressure"><xf:label>Blood Pressure: </xf:label></xf:input></div><div id="notes"><xf:textarea ref="Notes"><xf:label>Notes regarding<br/>visitwith patient:<br/></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="docTor/list">Back to List</a></body></html>

首先要注意实例数据中新增加了两个元素 BPressure 和 Notes。这两个字段保 存医生所测得的患者血压,并告诉医生可以输入文本字段。这里的 submit-info 和 load_data 提交元素 的 action 属性指向医生控制器。最后,还可以看到 XForm. 体中声明了两个新的 XForms 元素。

下面生成医生视图和控制器的 scaffolding。

医生视图和控制器

Rails scaffolding 为 Ruby 应用程序的开发提供了非常好的起点。生成的医生视图和控制器 scaffolding 如清单 2 所示。

清单 2. 生成医生视图和控制器的 scaffolding

ruby script/generate scaffold patient docTorexists app/controllers/exists app/helpers/create app/views/docTorexists 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/docTor/_form.rhtmlcreate app/views/docTor/list.rhtmlcreate app/views/docTor/show.rhtmlcreate app/views/docTor/new.rhtmlcreate app/views/docTor/edit.rhtmlcreate app/controllers/docTor_controller.rbcreate test/functional/docTor_controller_test.rbcreate app/helpers/docTor_helper.rbcreate app/views/layouts/docTor.rhtmlidentical public/stylesheets/scaffold.css

要注意很多东西已经写好了,Rails 仅创建了还没有的文件。接下来需要定义 docTor 控制器中的 grab 和 update 方法,如清单 3 所示。

清单 3. 定义 docTor 控制器中的 grab 和 update 方 法

 def grab  id = @request.env["HTTP_REFERER"].split('=')[1]  @patient = Patient.find(id)  doc = REXML::Document.new(@patient.information)  if doc.root.elements["Notes"] == nil then   el = REXML::Element.new("Notes")   doc.root.add el  end  if doc.root.elements["BPressure"] == nil then   el = REXML::Element.new("BPressure")   doc.root.add el  end  @patient.information = doc 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  @patient.update_attributes(params[:patient])  redirect_to :action => 'list' end

首先要注意,grab 方法和其他两个控制器(kiosk 与 triage)大不相同。这是因为, BPressure 和 Notes 这两个新元素目前对于数据库中新增和批准的记录还不存在。因此请求记录的时候 ,将搜索这两个新的 XML 元素,如果不存在,需要在通过 grab 视图返回 XForm. 之前加上。XML 文档中 BPressure 和 Notes 元素都存在之后,将患者信息字段设置为包含在 doc 变量中的新 XML。

讨 论 update 方法之前,首先将 grab.rhtml 从 triage 视图(app/views/triage/grab.rhtml)复制到 docTor 视图(app/views/docTor)。这样 grab 视图完成了。

update 方法没有增加新功能,但 必须将新的 XML 数据保存到 DB2 。

下面我们看看如何更新医生列表视图。

医生的列表视 图

通过这个视图,医生可以看到信息经过护士认可的所有患者的姓和名。修改 list 视图 (app/views/docTors/list.rhtml)如清单 4 所示。

清单 4. 修改医生的 list 视图

<h1>Listing patients</h1><br /><table><br />  <tr><br />    <th><%= "First Name" %></th><br />    <th><%= "Last Name" %></th><br />  </tr><br /><% for patient in @patients %><br /><%   if patient.approved=="true" then %><br />  <tr><br />    <td><% doc = REXML::Document.new(patient.information) %><br />      <%= doc.root.elements["FirstName"] %><br />    </td><br />    <td><br />      <%= doc.root.elements["LastName"] %><br />    </td><br />    <td><%= "<a href=/"../docTorPatient.xhtml?id=" +<br />             patient[:id].to_s + "/">View/Add Notes</a>" %></td><br />    <td><%= link_to 'Delete', { :action => 'destroy', :id => patient },<br />                                 :confirm => 'Are you sure?',<br />                                 :method => :post %></td><br />  </tr><br /><%   end %><br /><% end %><br /></table><br />...

这里输出姓名供医生查看。清单 4 中还要注意 View/Add Notes 链接,它指向 docTorPatient 表单。用户单击该链接将打开一个 XForm,和前面表单不同的是,医生可以在这里输入信 息(血压和注释)。

图 1. 医生 XForm

医生可以查看患者 的姓名,单击 View/Add Notes 链接在表单中打开(如图 2 所示)。

图 2. 医生和患者 XForm

在这里医生可以添加 Please describe your symptoms 文本框,输入病人的血压,在 Notes 框中记录诊 治过程中的特殊事项。提交后将返回到 图 1 所示的网页。

这样医生表单就完成了。接下来创建 患者查找表单。

患者查找表单

如果有很多病人,该怎么办?在繁忙的诊所里查找病人要花很多时间。这个表单允许医生和护士按照 姓氏查找患者,可以缩短手工搜索的时间。新表单需要一个新的 graball 视图,将所有病人放在一个 XML 文档中,然后将这个文档返回给 XForm。首先要创建一个新视图,然后创建新的 XForm。

创 建 graball 控制器

graball 控件如其名字所示,是在单一 XML 文件中返回数据库中所有患者的 新视图。在 docTor 视图目录(app/views/docTor/graball.rhtml)目录下创建一个新文件,内容如清单 5 所示。

清单 5. 编写 graball 视图

<%= "" %><%= "" %><%= "" %><%= "" %>

需要注意的是,该视图和 grab 视图一样,首 先将 Content-Type 头部设置为 “text/xml” 类型,这样 Mongrel 和 Firefox 就知道如何 处理它了。然后打开 Patients 标签并设置名称空间。有趣的是 for 循环:数据库中的每位患者都遍历 一次,在 XML 文章中生成对应的一组 … 标签。Info 标签有三个属性:

DbId — 患者在数据库中对应的 ID。

ViewEditLinkDoc — 这个局部变量包 含打开 docTorPatient 表单显示患者信息的链接。

ViewEditLinkTri — 类似于 ViewEditLinkDoc,这也是个局部变量,在 triagePatient 表单中显示患者信息。

显示 Info 起 始标签之后,从患者 XML 记录中检索病人的姓氏,就像在列表视图中检索一样(如 清单 4 所示)。结 束标签 最后把患者记录存入 XML。患者全部遍历之后,for 循环执行结束,写上 标签完成 XML。

请注意,医生控制器中没有对应的 graball 方法。代码如清 单 6 所示。

清单 6. 医生控制器中的 graball 方法。

 def graball@patient = Patient.find_by_sql("select * from patients");end

不需要根据 ID 等唯一标识符去查找,只要一条 SQL 语句要求返回所有的患者。这就是为 清单 5 中的 graball 视图抓取所有患者的方法。

下面开始编写患者查找表单。

患者查找 XForm

这是本系列教程中的最后一个 XForm!有了这个表单之后,医生和护士很快就能按照姓氏找 到病人。创建一个新的 XForm(lookupPatient.xhtml)保存到 public 目录下,其代码如清单 7 所示。

清单 7. lookupPatient 表单

<?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:xs="http://www.w3.org/2001/XMLSchema"   xmlns:xf="http://www.w3.org/2002/xforms"   xmlns:ev="http://www.w3.org/2001/xml-events"> <head>  <meta. http-equiv="Content-Type"     content="text/html; charset=ISO-8859-1" />  <title>Patient Lookup</title>  <xf:model id="patientModel">   <xf:instance xmlns="" id="searchLastName">    <search>     <LastName/>    </search>   </xf:instance>   <xf:instance xmlns="" id="patients">    <Patients><!--     <Info DbId="" ViewEditLinkDoc="" ViewEditLinkTri="">      <LastName/>     </Info>     ...-->    </Patients>   </xf:instance>   <xf:submission id="load_data"           action="http://localhost:3000/docTor/graball/0"           method="post"           replace="instance"           instance="patients"/>      <xf:action ev:event="xforms-ready">    <xf:dispatch name="xforms-submit" target="load_data"/>   </xf:action>  </xf:model> </head> <body>  <p>   <div id="searchLastName">    <xf:input ref="instance('searchLastName')//LastName"         incremental="true">     <xf:label>Search Last Name:</xf:label>    </xf:input>   </div>   <table>    <th>     <td width="200px">Last Name</td>     <td width="100px">View/Edit DocTor</td>     <td width="100px">View/Edit Triage</td>    </th>   </table>   <xf:repeat id="patientRepeat"         nodeset="instance('patients')//Info             [LastName=instance('searchLastName')//LastName]">    <table>     <tr>      <td width="200px">       <div id="LastName">        <xf:output ref="LastName"/>       </div>      </td>      <td width="100px">       <div id="viewDocTor">        <xf:trigger>         <xf:label>View/Edit Doc</xf:label>         <xf:action ev:event="DOMActivate">          <xf:setvalue ref="@ViewEditLinkDoc"            value="concat('docTorPatient.xhtml?id=',../@DbId)"/>          <xf:load ref="@ViewEditLinkDoc" show="new"/>         </xf:action>        </xf:trigger>       </div>      </td>      <td width="100px">       <div id="viewTriage">        <xf:trigger>         <xf:label>View/Edit Tri</xf:label>         <xf:action ev:event="DOMActivate">          <xf:setvalue ref="@ViewEditLinkTri"            value="concat('triagePatient.xhtml?id=',../@DbId)"/>          <xf:load ref="@ViewEditLinkTri" show="new"/>         </xf:action>        </xf:trigger>       </div>      </td>     </tr>    </table>   </xf:repeat>  </p>  <a href="docTor/list">Back to DocTor</a><br/>  <a href="triage/list">Back to Triage</a> </body></html>

该表单中有几个迄今还没有遇到的新元素。此外,它有两个实例文档需要分别管理。id 为 searchLastName 的第一个实例文档包含要搜索的患者姓氏。患者实例文档包括 load_data 提交元素加载 的 XML(加载 XForm. 调用医生 graball 视图时引发)。加载该实例数据后 XForm. 并没有特别的变化, 除非输入和患者 XML 实例数据中的某个姓氏相匹配的姓氏(如图 3 所示)。

图 3. lookupPatient 表单

清单 7 的 XForm. 中包含一个文本框,医生和护士可以输入匹配的姓氏。接下来设置了标题,一个用于要查找的姓氏,两个 用于按钮,让医生和护士在不同的表单中(docTorPatient 和 triagePatient)打开找到的患者的信息。 如果找到结果,就要用到 repeat 元素了。repeat 元素 nodeset 属性中的 XPath 语句指定了要在 repeat 语句中显示的 Info 元素。如果患者 XML 实例数据中有一个姓氏和文本框中输入的内容匹配,就 通过 XPath 找到对应的信息。第一列中显示姓氏,第二列中的按钮在 docTorPatient 表单中显示患者信 息,第三列的按钮在 triagePatient 表单中显示患者信息(如图 4 所示)。

图 4. lookupPatient 表单

匹配的患者数据显 示在表格的一行中。这种方法非常快捷,类似于 Ajax,是通过 “Search Last Name” 文本 框的 incremental=”true” 属性实现的(如 清单 7 所示)。在 docTorPatient 和 triagePatient 表单中显示数据只需要点击 图 4 中的两个按钮即可。

太方便了!我们已经完成 了关于如何使用 Ruby 和 DB2 pureXML 开发 XForms 的系列文章。

结束语

真了不起!为 了在本系列的最后一部分完成应用程序,我们开发了医生 XForm. 和患者查找 XForm,以便简化查找患者 的工作,因为可能有成千上万的患者记录等着去找。

本文配套源码

总结失败的原因能够让人越来越谨慎。

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

相关文章:

你感兴趣的文章:

标签云: