程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> 使用XForms和Ruby on Rails開發小型門診管理系統,第4部分

使用XForms和Ruby on Rails開發小型門診管理系統,第4部分

編輯:關於JAVA

實現醫生和患者搜索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/>visit
with 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 doctor
exists app/controllers/
exists app/helpers/
create app/views/doctor
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/doctor/_form.rhtml
create app/views/doctor/list.rhtml
create app/views/doctor/show.rhtml
create app/views/doctor/new.rhtml
create app/views/doctor/edit.rhtml
create app/controllers/doctor_controller.rb
create test/functional/doctor_controller_test.rb
create app/helpers/doctor_helper.rb
create app/views/layouts/doctor.rhtml
identical 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>
<table>
<tr>
<th><%= "First Name" %></th>
<th><%= "Last Name" %></th>
</tr>
<% for patient in @patients %>
<% if patient.approved=="true" then %>
<tr>
<td><% doc = REXML::Document.new(patient.information) %>
<%= doc.root.elements["FirstName"] %>
</td>
<td>
<%= doc.root.elements["LastName"] %>
</td>
<td><%= "<a href=\"../doctorPatient.xhtml?id=" +
patient[:id].to_s + "\">View/Add Notes</a>" %></td>
<td><%= link_to 'Delete', { :action => 'destroy', :id => patient },
:confirm => 'Are you sure?',
:method => :post %></td>
</tr>
<% end %>
<% end %>
</table>
...

這裡輸出姓名供醫生查看。清單 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 視圖

<% @headers["Content-Type"] = "text/xml; charset=utf-8" %><%=
"<Patients xmlns:xf=\"http://www.w3.org/2002/xforms\"
xmlns:xs=\"http://www.w3.org/2001/XMLSchema\"
xmlns:p=\"http://developerworks.ibm.com/patient\"
xmlns:ev=\"http://www.w3.org/2001/xml-events\">" %>
<% for pat in @patient %>
<%= "<Info DbId=\"" + pat.id.to_s +
"\" ViewEditLinkDoc=\"\" ViewEditLinkTri=\"\">" %>
<% doc = REXML::Document.new(pat.information) %>
<%= doc.root.elements["LastName"].to_s %>
<%= "</Info>" %>
<% end %>
<%= "</Patients>" %>

需要注意的是,該視圖和 grab 視圖一樣,首 先將 Content-Type 頭部設置為 “text/xml” 類型,這樣 Mongrel 和 Firefox 就知道如何 處理它了。然後打開 Patients 標簽並設置名稱空間。有趣的是 for 循環:數據庫中的每位患者都遍歷 一次,在 XML 文章中生成對應的一組 <Info>...</Info> 標簽。Info 標簽有三個屬性:

DbId — 患者在數據庫中對應的 ID。

ViewEditLinkDoc — 這個局部變量包 含打開 doctorPatient 表單顯示患者信息的鏈接。

ViewEditLinkTri — 類似於 ViewEditLinkDoc,這也是個局部變量,在 triagePatient 表單中顯示患者信息。

顯示 Info 起 始標簽之後,從患者 XML 記錄中檢索病人的姓氏,就像在列表視圖中檢索一樣(如 清單 4 所示)。結 束標簽 </Info> 最後把患者記錄存入 XML。患者全部遍歷之後,for 循環執行結束,寫上 </Patients> 標簽完成 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,以便簡化查找患者 的工作,因為可能有成千上萬的患者記錄等著去找。

本文配套源碼

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved