Перейти к тексту

Нажимая Отправить, Вы принимаете Условия использования developerWorks.

При первом входе в developerWorks для Вас будет создан профиль. Выберите информацию отображаемую в Вашем профиле — скрыть или отобразить поля можно в любой момент.

Вся введенная информация защищена.

  • Закрыть [x]

При первом входе в developerWorks для Вас будет создан профиль и Вам нужно будет выбрать Отображаемое имя. Оно будет выводиться рядом с контентом, опубликованным Вами в developerWorks.

Отображаемое имя должно иметь длину от 3 символов до 31 символа. Ваше Имя в системе должно быть уникальным. В качестве имени по соображениям приватности нельзя использовать контактный e-mail.

Нажимая Отправить, Вы принимаете Условия использования developerWorks.

Вся введенная информация защищена.

  • Закрыть [x]

XForms и Ruby on Rails в кабинете врача: Часть 4. Создание форм для врача и для поиска карточек пациентов

Тайлер Андерсон, независимый автор, Backstop Media
Тайлер Андерсон (Tyler Anderson) получил степень бакалавра по компьютерным наукам в Brigham Young University в 2004 и степень магистра по компьютерной технике в декабре 2005 тоже в Brigham Young University. Сейчас он работает инженером в фирме Stexar Corp., расположенной в Beaverton, Ore.

Описание:  Это четвертая часть серии из четырех статей, посвященной совместному использованию XForms, IBM® DB2® pureXML™ и Ruby для упрощения создания Web-приложений. В этой серии мы разрабатываем гипотетическое приложение для управления информацией о пациентах в кабинете врача. Вы получите представление об отдельных достоинствах каждой технологии, но также увидите, как объединить их друг с другом. В четвертой части мы продолжим разработку форм для кабинета врача и добавим новую форму для поиска пациентов по фамилии.

Дата:  24.08.2009
Уровень сложности:  средний
Активность:  3129 просмотров
Комментарии:  


Введение

Мы уже создали базу данных 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). Ссылки для загрузки приведены в разделе Ресурсы.


Форма для врача

Часто используемые сокращения

  • XML: Extensible Markup Language – расширяемый язык разметки

Форма для врача (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 в действии
Форма doctorPatient XForm

Врач может делать записи в текстовом окне 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
Форма lookupPatient

В теле формы из листинга 7 видно текстовое поле, в которое врач и медсестры вводят искомые фамилии. Затем следуют заголовки, один для найденной фамилии и два для кнопок, которые позволяют врачу и медсестрам открывать информацию по каждому найденному пациенту в отдельной форме (doctorPatient, а не triagePatient). Если результат обнаружен, вступает в действие элемент повторения. Оператор XPath атрибута nodeset элемента повторения определяет, какие элементы Info отображаются внутри элемента повторения. Если фамилия из экземпляра XML-данных пациента совпадает с фамилией, введенной в текстовое поле, значит, XPath обнаружил совпадение. Он отображает фамилию в первом столбце, кнопку вызова информации о пациенте в форме doctorPatient во втором столбце и кнопку вызова информации о пациенте в форме triagePatient в третьем столбце (см. рис. 4).


Рисунок 4. Форма lookupPatient в действии
Форма lookupPatient в действии

Данные о найденном пациенте отображаются в строках таблицы. Такая немедленная обработка в стиле Ajax возможна благодаря атрибуту incremental="true" в текстовом поле "Search Last Name" (поиск по фамилии) (см. листинг 7). Чтобы ввести данные о пациенте в любую из форм doctorPatient или triagePatient, просто нажмите одну из кнопок, изображенных на рисунке 4.

Удобно, не правда ли? На этом серия статей, посвященных созданию форм XForms с применением Ruby и DB2 pureXML, завершается.


Заключение

Итак, в последней части цикла из четырех статей, посвященных разработке приложения для кабинета врача, вы создали форму XForms для врача и последнюю форму для поиска карточек пациентов, которая облегчает задачу поиска среди, возможно, тысяч историй болезни.

Освоив XForms, Ruby on Rails и DB2 pureXML, вы поняли, что эти три технологии составляют отличную команду! Возможно, вы еще не совсем овладели ими, но в этом вам поможет раздел Ресурсы. Там вы найдете много полезных ссылок, которые позволят вам расширить знания и приобрести опыт по каждой из этих трех технологий. Удачи!



Загрузка

ОписаниеИмяРазмерМетод загрузки
Код примеров для части 4part4_doctorsOffice.zip15 KБHTTP

Информация о методах загрузки


Ресурсы

Научиться

Получить продукты и технологии

Обсудить

Об авторе

Тайлер Андерсон (Tyler Anderson) получил степень бакалавра по компьютерным наукам в Brigham Young University в 2004 и степень магистра по компьютерной технике в декабре 2005 тоже в Brigham Young University. Сейчас он работает инженером в фирме Stexar Corp., расположенной в Beaverton, Ore.

Помощь по сообщениям о нарушениях

Сообщение о нарушениях

Спасибо. Эта запись была помечена для модератора.


Помощь по сообщениям о нарушениях

Сообщение о нарушениях

Сообщение о нарушении не было отправлено. Попробуйте, пожалуйста, позже.


developerWorks: вход


Нужен IBM ID?
Забыли Ваш IBM ID?


Забыли Ваш пароль?
Изменить пароль

Нажимая Отправить, Вы принимаете Условия использования developerWorks.

 


При первом входе в developerWorks для Вас будет создан профиль. Выберите информацию отображаемую в Вашем профиле — скрыть или отобразить поля можно в любой момент.

Выберите ваше отображаемое имя

При первом входе в developerWorks для Вас будет создан профиль и Вам нужно будет выбрать Отображаемое имя. Оно будет выводиться рядом с контентом, опубликованным Вами в developerWorks.

Отображаемое имя должно иметь длину от 3 символов до 31 символа. Ваше Имя в системе должно быть уникальным. В качестве имени по соображениям приватности нельзя использовать контактный e-mail.

(Должно содержать от 3 до 31 символа.)


Нажимая Отправить, Вы принимаете Условия использования developerWorks.

 


Оценить эту статью

Комментарии

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=40
Zone=XML, Information Management
ArticleID=422568
ArticleTitle=XForms и Ruby on Rails в кабинете врача: Часть 4. Создание форм для врача и для поиска карточек пациентов
publish-date=08242009
author1-email=tyleranderson5@yahoo.com
author1-email-cc=troy@backstopmedia.com

Теги

Help
Используйте форму поиска, чтобы найти любой контент с данным тегом в My developerWorks. Используйте ползунок, чтобы отразить больше или меньше тегов.

КнопкаПопулярные теги отображает самые распространенные теги для данной области контента (например: Java, Linux, WebSphere).

Кнопка Мои теги отображает Ваши теги для данной области контента (например: Java, Linux, WebSphere).

Используйте форму поиска, чтобы найти любой контент с данным тегом в My developerWorks. Кнопка Популярные теги отображает самые распространенные теги для данной области контента (например: Java, Linux, WebSphere). Кнопка Мои теги отображает Ваши теги для данной области контента (например: Java, Linux, WebSphere).