 | Уровень сложности: средний Тайлер Андерсон, независимый автор, Backstop Media
24.08.2009 Это четвертая часть серии из четырех статей, посвященной совместному использованию XForms, IBM® DB2® pureXML™ и Ruby для упрощения создания Web-приложений. В этой серии мы разрабатываем гипотетическое приложение для управления информацией о пациентах в кабинете врача. Вы получите представление об отдельных достоинствах каждой технологии, но также увидите, как объединить их друг с другом. В четвертой части мы продолжим разработку форм для кабинета врача и добавим новую форму для поиска пациентов по фамилии.
Введение
Мы уже создали базу данных DB2 и три формы XForms, которые помогают пациентам и медсестрам работать со сведениями о пациентах. В качестве интерфейса обработки для добавления в базу данных новых карточек пациентов и последующего редактирования этой информации применялся Ruby on Rails. Теперь медсестра имеет возможность просматривать информацию, вносить необходимые поправки и утверждать введенные данные, чтобы пациент мог отправиться на прием к врачу.
В этой последней, четвертой статье мы создадим новое представление и контроллер для врача, а также две новые формы XForms для этого представления. Первая форма позволит врачу просматривать данные, введенные пациентами и утвержденные медсестрой, а также вводить дополнительную информацию, связанную с осмотром пациента. Затем мы разработаем форму, при помощи которой врачи и медсестры смогут искать карточки пациентов по фамилии.
Предварительные замечания
Эта статья предполагает знакомство с 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). Ссылки для загрузки приведены в разделе Ресурсы.
Форма для врача
Форма для врача (doctorPatient.xhtml) позволяет лечащему врачу видеть ту информацию, которую ввел пациент и проверила медсестра. При помощи этой формы врач может также вводить дополнительную информацию по результатам осмотра пациента. Поэтому форма doctorPatient аналогична форме triagePatient с несколькими изменениями (листинг 1). Назовем этот файл doctorPatient.xhtml и сохраним его в общей папке.
Листинг 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 указывают на контроллер doctor. Наконец, в теле формы объявлены два новых элемента XForms.
Теперь сгенерируем скаффолдинг для представления и контроллера doctor.
Представление и контроллер doctor
Скаффолдинг Rails служит превосходной исходной точкой для разработки приложения Ruby. Сгенерируем скаффолдинг представления и контроллера doctor, как показано в листинге 2.
Листинг 2. Генерация скаффолдинга представления и контроллера doctor
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 создает только отсутствующие файлы. Затем определим методы grab и update в контроллере doctor (листинг 3).
Листинг 3. Определение методов grab и update в контроллере doctor
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-элементов, и если их нет, они должны быть добавлены в XML до возврата в форму через представление grab. После добавления в документ XML обоих новых элементов поле с информацией о пациенте устанавливается в соответствии с новым кодом XML, содержащимся в переменной doc.
Прежде чем перейти к методу update, скопируйте grab.rhtml из представления triage (app/views/triage/grab.rhtml) в представление doctor (app/views/doctor). Представление grab готово!
Здесь метод update не несет в себе никакой новой функциональности, но явно необходим для сохранения новых данных XML в DB2.
Теперь отредактируем представление list для врача.
Представление list для врача
В этом представлении врач может видеть имена и фамилии пациентов, карточки которых утверждены медсестрой. Отредактируем представление 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>
...
|
В этот список выводятся имена и фамилии пациентов. Обратите также внимание на ссылку View/Add Notes в листинге 4, которая указывает на форму doctorPatient. Когда пользователь нажимает на эту ссылку, он открывает форму, позволяющую врачу вводить информацию (артериальное давление и заметки), которой не было в прежних формах (рисунок 1).
Рисунок 1. Так выглядит форма для врача.
Теперь врач может просматривать имена и фамилии пациентов и открывать карточку по ссылке View/Add Notes (рисунок 2).
Рисунок 2. Форма doctorPatient в действии
Врач может делать записи в текстовом окне Please describe your symptoms (укажите, пожалуйста, симптомы), вводить значение артериального давления пациента и делать любые другие замечания, относящиеся к осмотру, в окне Notes. После передачи этой информации возвращается Web-страница, приведенная на рисунке 1.
Форма для врача готова. Теперь создадим форму поиска карточек пациентов.
Форма поиска карточек пациентов
А что, если пациентов много, и список приходится долго прокручивать? Это усложняет задачу поиска пациентов. Форма, которая позволяет врачам и медсестрам искать карточки пациентов по фамилии, ускорит процесс. Для этой новой формы потребуется представление graball, которое помещает всех пациентов в один документ XML и возвращает его в форму XForms. Сначала создадим новое представление, а затем и саму форму.
Создание элемента управления graball
Элемент управления graball – это новое представление, которое собирает всех пациентов из базы данных в один XML-файл. Создайте новый файл в каталоге врача (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
— идентификатор пациента в базе данных;
-
ViewEditLinkDoc
— локальная переменная, содержащая ссылку на информацию о пациенте в doctorPatient;
-
ViewEditLinkTri
— это тоже локальная переменная, как и ViewEditLinkDoc, но она передает сведения о пациенте в форму triagePatient.
Когда отображается открывающий тег Info, фамилия пациента извлекается из его XML-записи, как в случае представления list (см. листинг 4). Замыкающий тег </Info> заканчивает ввод данного пациента в XML. Если пациентов много, выполняется цикл for, и замыкающий тег </Patients> завершает составление документа XML.
Заметьте, что соответствующий метод graball в контроллере doctor отсутствует. Определим его, как показано в листинге 6.
Листинг 6. Метод graball в контроллере doctor
def graball
@patient = Patient.find_by_sql("select * from patients");
end
|
Вместо поиска по уникальному идентификатору, такому как ID, оператор SQL запрашивает всех пациентов. В результате все пациенты из базы данных извлекаются в представление graball, определенное в листинге 5.
Затем мы создаем собственно форму поиска пациентов.
Форма поиска карточек пациентов
Это последняя форма, которую мы создадим в этой серии статей. При помощи этой удобной формы врач или медсестра могут легко искать карточки пациентов по фамилии. Создайте новую форму XForms (lookupPatient.xhtml), сохраните ее в общем каталоге и определите, как показано в листинге 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>
|
Эта форма содержит несколько новых элементов, еще не встречавшихся нам в этой серии. В ней есть два экземпляра документа, которыми нужно управлять отдельно. Первый экземпляр документа с идентификатором searchLastName содержит фамилию искомого пациента. Экземпляр документа пациента содержит код XML, загруженный элементом передачи load_data (он отображается путем вызова представления graball для врача при загрузке формы). После загрузки экземпляра данных вы не увидите в форме ничего особенного, пока не введете фамилию, совпадающую с одной из фамилий в списке из экземпляра XML пациента (см. рисунок 3).
Рисунок 3. Форма lookupPatient
В теле формы из листинга 7 видно текстовое поле, в которое врач и медсестры вводят искомые фамилии. Затем следуют заголовки, один для найденной фамилии и два для кнопок, которые позволяют врачу и медсестрам открывать информацию по каждому найденному пациенту в отдельной форме (doctorPatient, а не triagePatient). Если результат обнаружен, вступает в действие элемент повторения. Оператор XPath атрибута nodeset элемента повторения определяет, какие элементы Info отображаются внутри элемента повторения. Если фамилия из экземпляра XML-данных пациента совпадает с фамилией, введенной в текстовое поле, значит, XPath обнаружил совпадение. Он отображает фамилию в первом столбце, кнопку вызова информации о пациенте в форме doctorPatient во втором столбце и кнопку вызова информации о пациенте в форме triagePatient в третьем столбце (см. рис. 4).
Рисунок 4. Форма lookupPatient в действии
Данные о найденном пациенте отображаются в строках таблицы. Такая немедленная обработка в стиле Ajax возможна благодаря атрибуту incremental="true" в текстовом поле "Search
Last Name" (поиск по фамилии) (см. листинг 7). Чтобы ввести данные о пациенте в любую из форм doctorPatient или triagePatient, просто нажмите одну из кнопок, изображенных на рисунке 4.
Удобно, не правда ли? На этом серия статей, посвященных созданию форм XForms с применением Ruby и DB2 pureXML, завершается.
Заключение
Итак, в последней части цикла из четырех статей, посвященных разработке приложения для кабинета врача, вы создали форму XForms для врача и последнюю форму для поиска карточек пациентов, которая облегчает задачу поиска среди, возможно, тысяч историй болезни.
Освоив XForms, Ruby on Rails и DB2 pureXML, вы поняли, что эти три технологии составляют отличную команду! Возможно, вы еще не совсем овладели ими, но в этом вам поможет раздел Ресурсы. Там вы найдете много полезных ссылок, которые позволят вам расширить знания и приобрести опыт по каждой из этих трех технологий. Удачи!
Загрузка | Описание | Имя | Размер | Метод загрузки |
|---|
| Код примеров для части 4 | part4_doctorsOffice.zip | 15 KБ | 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 в кабинете врача, часть 2: Создание формы ввода данных о пациентах (Майкл Гальпин, developerWorks, декабрь 2007 г.): Комбинирование XForms, DB2 pureXML и Ruby для упрощения процесса создания Web-приложения. Во второй части этой серии мы приступаем к созданию гипотетического приложения, которое управляет информацией о пациентах в кабинете врача.
-
XForms и Ruby on Rails в кабинете врача, часть 3: Создание формы для врача и медсестры (Тайлер Андерсон, developerWorks, июнь 2008 г.): простое создание Web-приложений при помощи XForms, DB2 pureXML и Ruby. В части 3 мы создаем форму, позволяющую медсестре редактировать введенные данные.
- Чтобы как следует познакомиться с 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 г.) .
- Одно из первых углубленных руководств по GWT: Ajax for Java developers: Exploring the Google Web Toolkit (Philip McCarthy, developerWorks, июнь 2006 г.) (EN).
- Начните знакомство с 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 г.) .
- О библиотеке REXML для работы с XML в Ruby: XML Matters: The REXML library (David Mertz, developerWorks, март 2002 г.) (EN).
- Центр ресурсов Ajax на IBM developerWorks
- Домашняя страница XForms на сайте W3C (EN).
-
Сертификация IBM по XML: Как стать сертифицированным IBM разработчиком XML и сопутствующих технологий.(EN)
-
Техническая библиотека по XML: широкий спектр технических статей, руководств, стандартов и документации IBM. (EN)
-
Технические мероприятия и Web-трансляции developerWorks.(EN)
- Книжный магазин: книги на эти и другие технические темы.(EN)
Получить продукты и технологии
Обсудить
Об авторе  | |  | Тайлер Андерсон (Tyler Anderson) получил степень бакалавра по компьютерным наукам в Brigham Young University в 2004 и степень магистра по компьютерной технике в декабре 2005 тоже в Brigham Young University. Сейчас он работает инженером в фирме Stexar Corp., расположенной в Beaverton, Ore. |
Выскажите мнение об этой странице
|  |