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

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

編輯:關於JAVA

實現患者信息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 kiosk
exists app/controllers/
exists app/helpers/
create app/views/kiosk
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/kiosk/_form.rhtml
create app/views/kiosk/list.rhtml
create app/views/kiosk/show.rhtml
create app/views/kiosk/new.rhtml
create app/views/kiosk/edit.rhtml
create app/controllers/kiosk_controller.rb
create test/functional/kiosk_controller_test.rb
create app/helpers/kiosk_helper.rb
create app/views/layouts/kiosk.rhtml
identical 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::Base
end

可以看到,默認情況下 Patient 類僅僅擴展了 ActiveRecord。ActiveRecord 根據映射的數據庫表的列名動態創建訪問器。它有一個構造函數接受名稱/值對作為參數。應用程序控制器利用它直接傳入表單數據。利用這一點我們來修改 patient 類,如清單 7 所示。

清單 7. 修改後的 patient 類

require 'rexml/document'
class Patient < ActiveRecord::Base
def information=(value)
self[:information] = value.to_s
end
end

變動不大,但是很重要。我們希望在內部用字符串保存信息,這樣在 ActiveRecord 將信息插入數據庫的時候就能序列化為字符串。但是傳遞給模型的時候呢?由控制器來完成。清單 8 顯示了默認的控制器。

清單 8. 默認的 Kiosk 控制器

class KioskController < ApplicationController
def index
list
render :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 => 10
end
def show
@patient = Patient.find(params[:id])
end
def new
@patient = Patient.new
end
def create
@patient = Patient.new(params[:patient])
if @patient.save
flash[:notice] = 'Patient was successfully created.'
redirect_to :action => 'list'
else
render :action => 'new'
end
end
def edit
@patient = Patient.find(params[:id])
end
def update
@patient = Patient.find(params[:id])
if @patient.update_attributes(params[:patient])
flash[:notice] = 'Patient was successfully updated.'
redirect_to :action => 'show', :id => @patient
else
render :action => 'edit'
end
end
def destroy
Patient.find(params[:id]).destroy
redirect_to :action => 'list'
end
end

前面已經把 XForms 的動作 URL 定義為 /kiosk/create,因此將調用上面的 create 方法。Rails 認為提交的時候獲取的是一系列 HTML 表單元素而不是 XML 文檔。因此需要修改這個方法以便解析 XForms 發送的 XML 文檔。清單 9 顯示了修改後的 create 方法。

清單 9. 修改後的 create 方法

 def create
doc = REXML::Document.new("<Info></Info>")
params[:Info].each_pair do |key,value|
if (key.index(':') == nil) #namespace attributes
el = REXML::Element.new key
el.add_text value
doc.root.add el
else
doc.root.add_attribute key,value
end
end
@patient = Patient.new
@patient.information = doc
if @patient.save
flash[:notice] = 'Patient was successfully created.'
redirect_to :action => 'list'
else
render :action => 'new'
end
end

首先要注意,這裡使用 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 導航和提取數據。

本文配套源碼

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