 | Уровень сложности: средний Майкл Галпин, инженер по программному обеспечению, Vitria Technology
17.08.2009 Это вторая часть серии из четырех статей, посвященных совместному использованию XForms, IBM® DB2® pureXML™ и Ruby для упрощенного создания Web-приложений. Мы разработаем гипотетическое приложение для управления историями болезни в кабинете врача. Вы почувствуете преимущества каждой из технологий и увидите, как объединить их друг с другом. Во второй части мы приступим к реализации приложения.
Введение
В первой части этой серии из четырех статей мы начали проектировать Web-приложение, которое позволяет пациентам вводить информацию о себе в кабинете врача. Было показано, как применять XForms, DB2 pureXML и Ruby on Rails для создания такого приложения, и мы поэкспериментировали с совместным использованием этих технологий. Во второй части мы приступим к реализации приложения. Вы спроектируете свою первую форму XForms и создадите механизм Ruby on Rails для ввода данных из формы в DB2. Вы увидите, как эти три технологии можно использовать для создания приложения, всецело опирающегося на XML.
Предварительные замечания
 |
Часто используемые сокращения
- API: application programming interface – интерфейс прикладных программ
- CSS: Cascading Stylesheets - каскадные таблицы стилей
- UI: User Interface – интерфейс пользователя
- URL: Uniform Resource Locator - унифицированный указатель [информационного] ресурса
- XML: Extensible Markup Language - расширяемый язык разметки
- XSD: XML Schema Definition – определение схемы XML
|
|
Эта статья предполагает знакомство с XML и Web-приложениями в целом. Конечно, полезно предварительное знакомство с тремя основными технологиями, XForms, DB2 pureXML и Ruby on Rails, но это не обязательно. При написании статьи использовался плагин Mozilla XForms версии 0.8.0.3. Он обеспечивает поддержку XForms в любом браузере Mozilla, таком как 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. В этой статье применяется также Web-сервер Mongrel в сочетании с Rails. Его можно получить через Ruby Gems (просто наберите в командной строке gem install). Ссылки для загрузки приведены в разделе Resources.
Сведения о пациенте
В первой части рассказывалось, как при помощи технологий XForms, DB2 pureXML и Ruby on Rails создать интерфейс пользователя и обрабатывающую часть приложения на базе XML. Преимущество этой конструкции заключается в том, что она целиком основана на XML. Конструкция модели данных XML определяет, как реализован интерфейс пользователя на основе XForms и как извлекаются данных из DB2 с использованием Ruby on Rails в обрабатывающей части. Поэтому логично начать разработку этого приложения с конструирования модели данных 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>
|
В основном это простые строки, за несколькими исключениями. Среднее имя должно быть необязательным полем. Возраст должен быть неотрицательным целым числом. То же справедливо для суммы совместного платежа. Policy holder (наличие страховки) – это логический флаг. Идентификатор может быть трехзначным, двухзначным и четырехзначным числом. С учетом всего этого в листинге 2 приведена XML-схема для описания модели сведений о пациенте.
Листинг 2. Схема Patient
<?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 реализовать довольно просто. Достаточно создать элементы формы, соответствующие элементам модели данных. Тип элемента формы основан на типе данных элемента данных. С учетом этого в листинге 3 показана реализация XForms для ввода информации о пациенте.
Листинг 3. Форма для ввода сведений о пациенте
<?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. У нас есть одна модель и одна реализация. Это пустая версия определенной выше модели сведений о пациенте. Есть также процесс передачи, входящий в состав модели. Он переносит модель по указанному в атрибуте action адресу URL. В теле формы имеется ряд элементов XForms. Каждый элемент связан с реализацией модели посредством XPath. Какие бы значения ни вводил пользователь, данные формы будут связаны с реализацией модели. Загрузив XForms в браузер, вы увидите что-то вроде того, что изображено на рисунке 1.
Рисунок 1. Форма для пациента
Пусть это не самая красивая Web-страница, но это работающая форма XForms. Стоит обратить внимание на несколько интересных вещей:
- Во-первых, это XHTML, а не обычная страница HTML. Если заменить расширение на .html или .htm, она будет обрабатываться неправильно. Дело в том, что для XForms требуется XHTML, а на странице HTML плагин Mozilla запускаться не будет.
- Далее, так как это XHTML, CSS все же поддерживается. Это простейший способ изменить облик страницы. CSS удобно использовать для проверки данных.
- Наконец, заметим, что в качестве адреса URL выбран http://localhost:3000/patient.xhtml. В приведенном выше примере страница обслуживается из приложения Ruby on Rails с применением Web-сервера Mongrel. Это статическая страница, поэтому можно просто скопировать ее в общий каталог своего приложения Rails. Можно использовать Web-сервер по умолчанию WEBrick, но он требует дополнительного конфигурирования для обслуживания страниц XHTML. Для Mongrel никакого такого конфигурирования не нужно.
Как уже упоминалось, передача формы вызывает действие POST экземпляра модели. Однако, прежде чем начать этот процесс, нужно выполнить некоторую проверку.
Проверка
Одна из самых типичных задач ввода данных – это проверка вводимой информации. Ее часто бывает предпочтительно выполнять со стороны клиента, чтобы предотвратить передачу в центральную систему ошибочных данных. Обычно это предусматривает написание сценария JavaScript для извлечения данных с последующим применением к ним некоторого правила (возможно, регулярного выражения). К счастью, XForms несколько упрощает эту задачу. Так как в основе XForms лежит XML, проверка имеет хорошо определенный синтаксис в XML: XML-схему. Добавим проверку XForms с помощью предварительно определенной схемы (листинг 2), как показано в листинге 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. XForms с проверкой и CSS.
Чтобы отправить форму, пользователь должен заполнить нужные поля. Когда значение введено, цвет поля автоматически изменяется, а фокус перемещается в следующее поле формы. Подумайте, как все это пришлось бы писать на JavaScript. Вместо этого мы создали приложение при помощи XSD и некоторых элементов CSS.
XForms предоставляет много возможностей для проверки. XML-схему использовать не обязательно, но это самый простой способ, особенно если данные легко описать при помощи схемы. Если проверка выполняется на стороне клиента, на стороне сервера можно сосредоточиться на обработке переданных данных.
Передача формы
Вы, должно быть, заметили, что URL для передачи формы уже определен. Тем, кто знаком с Ruby on Rails, этот URL должен что-то напомнить. В соответствии с соглашением о конфигурации и с соглашением Rails URL
/patient/create соответствует действию по созданию контроллера пациента. Это можно легко настроить с применением сценария генерации Ruby, как в листинге 5.
Листинг 5. Создание скаффолдинга для пациента
>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. Теперь обратите внимание на модель и контроллер и посмотрите, как модифицировать их, чтобы сохранить XML из XForms.
Модель и контроллер Rails
Скаффолдинг Rails используется для ускорения разработки приложения. Во многих приложениях Rails скаффолдинг можно использовать для управления взаимодействием с базой данных без внесения каких-либо изменений в контроллер. Это возможно благодаря использованию кода объектно-реляционного отображения в классе ActiveRecord Rails, который является базовым классом для всех моделей (включая класс patient).
ActiveRecord не предназначен для управления XML, поэтому сгенерированные классы нужно модифицировать. Начнем с класса patient (листинг 6).
Листинг 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
|
Ранее мы определили действительный URL для XForms как /kiosk/create, поэтому будет вызван приведенный выше метод create. Rails «думает», что это последовательность элементов формы HTML, а не документ XML. Поэтому мы слегка модифицируем этот метод, чтобы обрабатывать XML-документ, который передается написанной нами формой XForms. В листинге 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
|
Первое, что бросается в глаза, - это то, что для создания XML-документа используется REXML. Это стандартная библиотека в составе Ruby. XML-документ из XForms поступает в параметр Info и обрабатывается как объект. Достаточно повторить его и вернуть в XML, и Rails введет документ в базу данных. Теперь его можно испытать.
Тестирование приложения
Чтобы испытать приложение, запустите сервер обычной командой ruby
script/server start. Затем наведите браузер на XForms, как на рисунке 2. Заполните форму и нажмите на кнопку Submit Information (передать информацию). Вы увидите экран, изображенный на рисунке 3.
Рисунок 3. Список пациентов
Откуда взялся пользовательский интерфейс? Это стандартный UI списка, предоставляемый скаффолдингом Rails. Заметьте, что в поле Info он отображает неформатированный текст XML. Если прокрутить экран вправо, вы увидите элементы управления для просмотра, редактирования и удаления пациентов. Просмотр и удаление работают как надо. Но не работает редактирование, и ссылка New Patient (новый пациент) внизу экрана тоже не работает. Нужно модифицировать ссылки для XForms, так как именно он используется для ввода данных. В этом вам поможет часть 3 настоящей серии статей.
Заключение
Мы рассмотрели применение XForms для создания формы ввода данных о пациентах. XForms обеспечивает включение этих данных в XML-документ и даже может выполнить проверку по схеме XML. Приложение передает этот XML-документ в контроллер Ruby on Rails. Ruby облегчает обработку этих данных как XML и преобразует XML в строку. DB2 распознает XML, преобразованный в последовательную строку, и может сохранять его в естественном виде с использованием технологии pureXML. Rails может даже отобразить эти данные без какой-то специальной работы с вашей стороны. Теперь можно использовать синтаксис DB2 XML/SQL для запроса XML-данных или для их извлечения, а Ruby – для навигации и выборки данных.
Загрузка | Описание | Имя | Размер | Метод загрузки |
|---|
| Код примеров для Части 2 | part2_doctorsOffice.zip | 7KB | HTTP |
|---|
Ресурсы Научиться
- Оригинал статьи (EN).
-
XForms и Ruby on Rails в кабинете врача, часть 1: Настройка IBM DB2 9 pureXML (Майкл Гальпин, developerWorks, декабрь 2007 г.): о том, как XForms, DB2 pureXML и Ruby on Rails помогают ускорить создание Web-приложений на основе XML.
-
XForms и Ruby on Rails в кабинете врача, часть 3: Создание формы для врача и медперсонала (Тайлер Андерсон, developerWorks, июнь 2008 г.): Простое создание Web-приложений при помощи XForms, DB2 pureXML и Ruby. В части 3 мы создаем форму для редактирования данных о пациентах медперсоналом.
-
XForms и Ruby on Rails в кабинете врача, часть 4: Создание форм для врача и для поиска карточек пациентов (Тайлер Андерсон, developerWorks, июнь 2008 г.): Интеграция XForms, IBM DB2 pureXML и Ruby для быстрого создания Web-приложений на базе XML. Полный пример приложения с новой формой XForms для поиска пациентов по фамилии.
- Чтобы как следует познакомиться с XForms, прочтите серию статей из трех частей Introduction to XForms [Введение в XForms](Chris Herbroth, developerWorks, сентябрь 2006 г.) (EN).
- Знаете ли вы, что XForms и Ajax можно использовать вместе? Вот как это делается в XForms: Combining Ajax and XForms [Комбинирование Ajax и XForms](Nicholas Chase, developerWorks, октябрь 2006 г.).
- Дальнейшее углубление в XForms и Ajax при помощи их использования с Google Web Toolkit: Integrate XForms with the Google Web Toolkit, Part 1: Introducing GWT's JavaScript Native Interface (Michael Galpin, developerWorks, сентябрь 2007 г.) (EN).
- Одно из первых углубленных руководств по GWT: Ajax for Java developers: Exploring the Google Web Toolkit (Philip McCarthy, developerWorks, июнь 2006 г.) .
- Начните знакомство с Ruby on Rails и DB2 с An introduction to Ruby on Rails for DB2 developers [Введение в Ruby on Rails для разработчиков DB2](Edd Dumbill, developerWorks, июнь 2006 г.) (EN).
- Все о совместном использовании DB2 и Ruby on Rails: DB2 and Ruby on Rails, Part 1: Getting started with DB2 and Ruby on Rails (John Chun, et al., developerWorks, май 2007 г.) (EN).
- Как применять pureXML из DB2 вместе с Ruby on Rails: DB2 and Ruby on Rails, Part2: DB2 and pureXML with Ruby on Rails (John Chun, et al., developerWorks, июнь 2007 г.) (EN).
- Как использовать DB2 для усиления встроенных средств тестирования в Rails: DB2 and Ruby on Rails, Part 3: Testing with DB2 and Ruby on Rails (John Chun, et al., developerWorks, июнь 2007 г.) (EN).
- Обзор последних усовершенствований DB2: Overview of new DB2 Version 9.5 pureXML enhancements (Manaj Sardana, developerWorks, ноябрь 2007 г.) (EN).
- Использование XQuery с DB2: Query DB2 XML data with XQuery (Don Chamberlin and Cynthia Saracco, developerWorks, апрель 2006 г.) (EN).
- О библиотеке REXML для работы с XML в Ruby: XML Matters: The REXML library (David Mertz, developerWorks, марта 2002 г.) (EN).
- Центр ресурсов Ajax на IBM developerWorks
(EN)
- Домашняя страница XForms на сайте W3C (EN).
-
IBM XML certification: Как стать сертифицированным IBM разработчиком XML и сопутствующих технологий.
-
Техническая библиотека по XML: широкий спектр технических статей, руководств, стандартов и документации IBM. (EN)
-
Технические мероприятия и Web-трансляции developerWorks(EN)
- Книжный магазин: книги на эти и другие технические темы.(EN)
-
Подкасты.(EN)
Получить продукты и технологии
Обсудить
Об авторе  | |  | Майкл Галпин (Michael Galpin) имеет учёную степень по математике в Калифорнийском Технологическом институте. Он является Java-разработчиком с конца 90-х гг. и работает инженером по программному обеспечению в Vitria Technology, в Саннивейл, Калифорния. |
Выскажите мнение об этой странице
|  |