Создание прототипов Web-приложений с помощью CouchDB и Bootstrap

Отделите Web-дизайн от дизайна базы данных, а затем снова соедините их

Сочетание СУБД Apache CouchDB с инфраструктурой Twitte Bootstrap позволяет организовать быструю разработку Web-приложений, отделив уровень представления от уровня базы данных. СУБД CouchDB известна как удобный инструмент разработки баз данных, особенно для Web-сайтов. Что касается интерфейсной части, то в последнее время появляется все больше инструментов с открытым исходным кодом для прототипирования и даже полного развертывания сайтов. Среди них выделяется инфраструктура Bootstrap, предназначенная для разработки Web-интерфейсов. Узнайте о разработке на Bootstrap с использованием CouchDB для хранения данных.

Юч Огбуджи, Главный консультант, Fourthought

Юч Огбуджи (Uche Ogbuji) - консультант и один из основателей Fourthought Inc., компании, занимающейся поставками программного обеспечения и предоставлением консалтинговых услуг в области XML-решений для корпоративного управления знаниями. Fourthought разрабатывает 4Suite, платформу с открытым исходным кодом, для XML, RDF и приложений по управлению знаниями. Юч Огбуджи - инженер в области вычислительной техники, он родился в Нигерии, сейчас живет и работает в Боулдер-Сити (Boulder), штат Колорадо, США. С ним можно связаться по адресу uche@ogbuji.net.



16.01.2014

Apache CouchDB – это система управления базами данных (СУБД) нового поколения, в которой реализована концепция NoSQL. Первичная информация хранится в ней в виде JSON-документов. CouchDB также поддерживает более общие форматы документов посредством управляемых вложений. Однако она не поддерживает классические табличные данные, к которым выполняются SQL-запросы, господствовавшие в мире СУБД на протяжении десятилетий. Другой ключевой характеристикой CouchDB является то, что все ее операции представляют собой простые HTTP-запросы в REST-форме. Такая архитектура позволяет использовать CouchDB на сервере с любой операционной системой и с помощью любого инструментария. Она также позволяет использовать CouchDB в качестве сервера для Web-сайтов и Web-приложений.

Существует много руководств по CouchDB, которые помогут начать разработку приложений с помощью встроенных JavaScript-библиотек и связанных инструментов, таких как CouchApp (см. раздел Ресурсы). Однако в этой статье я продемонстрирую быстрое создание прототипов Web-сайтов с помощью CouchDB и простой инфраструктуры создания статических Web-сайтов.

Несколько слов о REST

REST – это архитектурный стиль построения слабо связанных Web-приложений, основанный на использовании именованных ресурсов (например, URL, URI и URN), а не сообщений. REST использует элементы протокола WWW HTTP, такие как запросы GET и POST.

Одним из новых популярных инструментов для быстрого создания интерфейса Web-сайта является Bootstrap. Система Bootstrap была разработана инженерами Твиттера для обуздания неразберихи в платформах и инструментальных средствах, которые они использовали для создания Web-сайтов. Bootstrap предоставляет согласованную инфраструктуру для создания интерфейсов Web-приложений. Она позволяет с легкостью проектировать красивые сайты с помощью CSS-элементов для разметки, форм, кнопок, таблиц, сеток, навигации, извещений и многих других элементов. В этой статье я покажу, как можно быстро разработать интерфейсную часть (с помощью Bootstrap) и серверную часть (с помощью CouchDB) даже сложного Web-приложения.

Почему бы не разработать прототип полностью в CouchDB?

Хотя во многих учебных пособиях демонстрируется, что с помощью CouchDB можно легко разработать полностью работоспособный Web-сайт, делать это не рекомендуется. При этом возникает огромный соблазн пойти кратчайшим путем и использовать тот же подход после публикации сайта. Однако с точки зрения безопасности и обслуживания лучше отделить серверную базу данных от интерфейса. В статье описываются различные варианты защиты работающего экземпляра CouchDB для обеспечения конфиденциальности данных. Безопасность всегда требует бдительности и компетентности. Поскольку Web-сайты, основанные на статических файлах, существуют дольше, они лучше изучены, а их инструменты управления являются наиболее зрелыми.

Отделение CouchDB от интерфейса сайта дает еще одно преимущество – возможность использования во время Web-разработки нескольких типовых инфраструктур:

  • СУБД для работы с данными.
  • Web-сервер или система управления контентом.
  • Инфраструктура Web-дизайна.

В этой статье используются CouchDB, Apache HTTP Server и Bootstrap.

Требования к персоналу, квалификация и критерии выбора технологии для каждого из этих слоев зачастую различны. Желательно, чтобы решения для одного слоя, не зависели от решений для другого. Кроме того, имеются динамические компоненты, такие как сети доставки контента, среды тестирования, промежуточное ПО для обеспечения безопасности и т.д. Чем больше гибкость комбинирования этих компонентов, тем легче будет обслуживать и совершенствовать систему в среднесрочной и долгосрочной перспективе.

Технологии, выбранные для этой статьи, соответствуют моей специализации – управление базами данных. Apache и Bootstrap – это лишь инструменты, которые помогают быстро разработать приложение с нуля. После создания основных элементов, безусловно, потребуется сотрудничество с другими специалистами. Возможно, разработчик промежуточного ПО предпочтет Web-серверную инфраструктуру (например, Django или Ruby on Rails) или даже систему управления контентом (например, WordPress), поэтому я использую Apache таким образом, что его можно легко заменить, не сильно затрагивая другие слои. Web-дизайнер скорее всего предпочтет разработку дизайна вручную, а не с помощью Bootstrap, поэтому я использую Bootstrap таким образом, что ее тоже можно легко заменить. Благодаря современным инструментам и механизмам подобный подход к созданию прототипов Web-приложений не намного сложнее, чем при использовании одного монолитного пакета технологий.

Перед началом работы

Заполнение контейнеров страницы

Страница нашего прототипа сайта использует JQuery для загрузки документов из CouchDB в теги div. Я использовал Ajax-функции JQuery, а не плагин JQuery, имеющийся в CouchDB и CouchApp. Плагин удобен, но он тесно связывает CouchDB и Web-сайт, поскольку страницы сайта являются вложениями базы данных. Я предпочитаю разделить их, особенно в процессе разработки. Помимо прочего это позволяет при необходимости менять серверную часть. Для загрузки страницы я использую простой JavaScript-код, который включен в файл для загрузки (poquotes.js), сопровождающий данную статью.

Я создам простое демонстрационное Web-приложение – сайт для поэтических цитат. Для получения информации по установке CouchDB обратитесь в раздел Ресурсы. Запустив CouchDB на сервере, загрузите простой пакет Twitter Bootstrap (состоящий только из CSS и JavaScript) или полный пакет проекта. В данной статье используется полный пакет.

Я начал с примера страницы fluid.html из пакета Twitter Bootstrap. Я сократил этот файл, указал путь к CSS и сценариям JavaScript, удалив .../assets/, а также заменил статический контент примера контентом своего сайта. Результат я сохранил в файл index.html, который входит в пакет исходных кодов, сопровождающий данную статью (см. раздел Загрузка). Значительная часть HTML-заголовка страницы показана в листинге 1.

Листинг 1. Часть заголовка страницы index.html
<!-- Стили -->
<link href="css/bootstrap.css" rel="stylesheet">
<style type="text/css">
  body {
    padding-top: 60px;
    padding-bottom: 40px;
  }
  .sidebar-nav {
    padding: 9px 0;
  }
</style>
<link href="css/bootstrap-responsive.css" rel="stylesheet">

<!-- HTML5 прокладка для поддержки элементов HTML5 браузером IE6-8 -->
<!--[если это IE 9]>
  <script src="//html5shim.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
</head>

В листинге 2 приведена часть таблицы index.html, в которой отображаются цитаты, загружаемые из CouchDB.

Листинг 2. Часть таблицы index.html, в которой отображаются цитаты
<div class="row-fluid">
  <div class="span4 featured-quote">
    <major>Poet's name</major>
    <p>Body of quote here.</p>
    <p><a class="btn" href="#">View details &raquo;</a></p>
  </div><!--/span-->
  <div class="span4 featured-quote">
    <major>Poet's name</major>
    <p>Body of quote here.</p>
    <p><a class="btn" href="#">View details &raquo;</a></p>
  </div><!--/span-->
  <div class="span4 featured-quote">
    <major>Poet's name</major>
    <p>Body of quote here.</p>
    <p><a class="btn" href="#">View details &raquo;</a></p>
  </div><!--/span-->
</div><!--/row-->

Эта страница также содержит механизм для взаимодействия с базой данных. В частности, на боковой вкладке имеется форма для ввода новых цитат. Пользователь получает доступ к форме, нажав ссылку, которая вызывает функцию jQuery, отображающую форму. В листинге 3 приведена разметка формы. (Первые две строки <input> разделены из-за ограничений ширины страницы для этой статьи.)

Листинг 3. Форма для ввода новых цитат на странице index.html
<a href="#popup" id="popup">Click to create a new quote</a>
<div>
  <form id="newquote" action="index.html">
    <fieldset>
      <legend>The quote</legend>
      <label for="author">Author's Name</label>
      <input id="author" name="author" type="text" placeholder="First and last name" 
          required="required" autofocus="autofocus">
      <label for="text">Text of the quotation</label>
      <input id="text" name="text" type="textarea" placeholder="Text of the quote here" 
          required="required">
    </fieldset>
    <fieldset>
      <legend>The work</legend>
      <label for="title">Title of the work</label>
      <input id="title" name="title" type="text" required="required">
      <label for="link">Link to the work</label>
      <input id="link" name="link" type="text" required="required">
      <label for="year">Year of the work</label>
      <input id="year" name="year" type="text" required="required">
    </fieldset>
    <input id="donewquote" type="submit" value="Add quote" />
  </form>
</div>

В листинге 4 приведен фрагмент кода в конце тела страницы index.html, который загружает необходимый JavaScript-код. Последняя строка script загружает код для работы с базой данных цитат poquotes в CouchDB.

Листинг 4. Загрузка JavaScript-кода в конце тела страницы index.html
<!-- Размещено в конце документа, что ускорит загрузку страниц -->
  <script src="js/jquery-1.7.1.js"></script>
  <script src="js/bootstrap.js"></script>

  <script src="js/poquotes.js"></script>

</body>

Менее чем за 5 минут работы в Bootstrap я получил базовый Web-сайт с самыми современными функциями, включая элегантную поддержку старых браузеров и мобильных устройств. При создании своего собственного Web-сайта вы можете изменить цвета, шрифты, изображения и другие элементы в соответствии с вашим дизайном. Идеи для дизайна можно почерпнуть в галерее Bootstrap (см. раздел Ресурсы).


Подготовка данных

В листинге 2 обратите внимание на элементы div класса featured-quote. В эти элементы я буду загружать данные из CouchDB. На главной странице предусмотрено место для шести цитат, которые динамически загружаются сценарием страницы и заменяют текущий стандартный текст.

Перейдите в браузерную консоль CouchDB Futon (например, по адресу http://localhost:5984/_utils/) и создайте базу данных poquotes (см. рисунок 1).

Рисунок 1. Создание базы данных poquotes со страницы CouchDB Futon
Рисунок 1. Создание базы данных poquotes со страницы CouchDB Futon

В листинге 5 приведен пример документа, который содержит информацию для цитаты. (Четвертая строка делится на две из-за ограничений ширины страницы для этой статьи.)

Листинг 5. Пример JSON-документа для цитаты
{
    "type": "quote",
    "author": "Thomas Hardy",
    "text": "And as the smart ship grew<br>In stature, grace, and hue<br>
In shadowy silent distance grew the Iceberg too.",
    "work": {
            "title": "The Convergence Of The Twain",
            "link": "http://www.poetryfoundation.org/poem/176678",
            "year": 1915
    }
}

Используя cURL, я загрузил этот файл под именем q1.json в новую базу данных.

curl -u user:passwd -X POST http://localhost:5984/poquotes \
 -H 'Content-Type: application/json' -d @q1.json
{"ok":true,"id":"ca42f5a16ca1905978afdeda68c116c2",
"rev":"1-7fe040eb6d322a35a86d2f871b100ff0"}

Ответ от CouchDB, начинающийся с {"ok", означает, что документ был добавлен; он также содержит сгенерированный идентификатор (ID) и номер редакции нового документа. RESTful-природа СУБД CouchDB позволяет создавать прототипы наборов данных для сайта почти так же просто, как в файловой системе. Futon также можно использовать для добавления документов. Загружаемый пример кода для этой статьи включает в себя шесть документов цитат, которых достаточно для заполнения сетки целевой страницы.


Подготовка основного запроса

Я использовал Futon, чтобы разработать представление для загрузки на Web-страницу необходимых документов. С помощью Futon можно создавать временные представления, тестировать их, а затем сохранять для конкретного использования. Если возможно, создавайте представления в начале цикла разработки, когда в базе данных есть всего несколько документов, поскольку временные представления могут замедлять работу. В листинге 6 приведен JavaScript-код представления.

Листинг 6. Использование представления CouchDB для получения всех документов цитат, проиндексированных по году издания источника
function(doc) {
  if (doc.type == "quote") {
    emit(doc.work.year, doc);
  }
}

Это простое представление вполне решает мою задачу – индексирует результаты по году издания источника, поскольку именно таким образом я хочу отсортировать записи на странице. Чтобы добавить это представление в базу данных, нажмите View и выберите Temporary view. Затем вставьте код листинга 6 в поле Map Function. Нажмите кнопку Run, после чего должна отобразиться таблица с шестью документами. Если все получилось, сохраните представление под именем by_year. При этом представление перестанет быть временным. Теперь можно протестировать это представление с помощью cURL:

curl "http://localhost:5984/poquotes/_design/poquotes/_view/\
by_year?&descending=true&limit=6"

Параметры GET (&descending=true&limit=6) задают способ доставки результатов запроса к базе данных. В нашем случае возвращается шесть самых "свежих" документов в порядке убывания, при этом документ с самым большим значением в поле года выводится первым.


Междоменные ограничения

Одной из проблем при быстрой разработке прототипов слабо связанных многослойных Web-приложений являются ограничения междоменных запросов в браузерах. По соображениям безопасности сценарии в браузере могут выполнять HTTP-запросы только к тому же порту на том же хосте, где находится исходная страница. Есть несколько подходов к решению этой проблемы. Один из них заключается в использовании JSONP (JSON с дополнениями; см. раздел Ресурсы). В листинге 7 приведен фрагмент файла poquotes.js, который загружает записи в целевые теги div.

Листинг 7. JavaScript- и jQuery-код для загрузки целевой страницы с цитатами
...
    root: "http://localhost:5984/",
...
    max_quotes: 6,

    //Вызывается при первой загрузке HTML-страницы
    loadPage: function()
    {
        var six_latest = poq.root + "poquotes/_design/poquotes/_view/by_year?&limit="
            + poq.max_quotes + "&descending=true&callback=?";
        $.getJSON(six_latest, poq.handleMainQuotes);
...
    },

    //Вызывается с результатом Ajax-вызова для загрузки документов цитат
    handleMainQuotes: function(json)
    {
        //Загружает до шести записей, имеющихся в наличии
        quote_count = Math.min(poq.max_quotes, json["total_rows"])
        for (var i=0; i<quote_count; i++) {
            var doc = json["rows"][i]["value"]
            var year = doc["work"]["year"].toString()
            var title = doc["work"]["title"].toString()
            var link = doc["work"]["link"].toString()

            //Создает HTML-фрагмент из полей каждого документа цитаты
            qblock = $("<div class='span4 featured-quote'></div>")
              .append("<major>" + doc["author"] + "</major>")
              .append("<p style='font-size: 80%; height: 8em;'>" + doc["text"] + "</p>")
              .append("<p>" + year + "</p>")
              .append("<p><a href='" + link + "'>" + title + "</a></p>")
              .append("<p><a class='btn' href='#'>View details &raquo;</a></p>")
            //jQuery-селектор eq для поиска целевого div, соответствующего индексу цикла
            $('div.featured-quote:eq(' + i.toString() + ')').replaceWith(qblock);
        }
    },

В листинге 7 в конец URL добавляется callback=? для загрузки документов. Это указывает JQuery использовать JSONP для Ajax-запроса GET, извлекающего документы из CouchDB, поскольку порт базы данных отличается от порта Web-интерфейса. При запросе к базе данных на другом хосте нужно использовать этот же прием.

Сделать так, чтобы Ajax-запросы могли использовать другие (отличные от GET) методы, несколько сложнее. В листинге 8 приведен фрагмент файла poquotes.js, который создает новую форму и отправляет ее в базу данных.

Листинг 8. JavaScript- и JQuery-код для включения полей формы в запись и отправки ее в CouchDB с помощью метода POST
...
    dbroot: "db/",
...
    //Вызывается при первой загрузке HTML-страницы
    loadPage: function()
    {
...
        $('#donewquote').click(function() {
            var db_link = poq.dbroot + "poquotes";
            var record = {
                "type": "quote",
                "author": $("#author").val(),
                "text": $("#text").val(),
                "work": {
                    "title": $("#title").val(),
                    "link": $("#link").val(),
                    "year": parseInt($("#year").val())
                }
            };
            $.ajax({
                url : db_link,
                data : JSON.stringify(record),
                contentType : "application/json", 
                type : 'POST',
                processData : false,
                dataType : "json",
                success : function(resp) {
                    alert("New document created: " + JSON.stringify(resp));
                }
            });
            return false;
        });
        //Установить сворачиваемую форму для добавления новых цитат
        $('#popup').click(function(){
            $("#newquote").slideToggle();
        });
        //Создать сворачиваемую форму для добавления новых цитат
        $("#newquote").slideToggle();
    },

В листинге 8 запрос POST выполняется к тому же хосту и порту, но по URL /db/. Я применяю стандартный прием настройки обратного прокси с этого URL на хост и порт CouchDB. В частности, я использую директиву ProxyPass HTTP-сервера Apache. Хотя детали этого метода зависят от настройки, он удобен для создания Web-прототипа с эффективным разделением слоев браузера и сервера.


Внешний вид интерфейса

На рисунке 2 изображена впервые загруженная страница работающего примера после заполнения целевых тегов div записями базы данных.

Рисунок 2. Окно браузера после загрузки страницы index.html с Web-сервера Apache
Рисунок 2. Окно браузера после загрузки страницы index.html с Web-сервера Apache

Чтобы отобразить форму для добавления новой цитаты, нажмите Click to create a new quote (см. рисунок 3).

Рисунок 3. Страница index.html с открытой формой
Рисунок 3. Страница index.html с открытой формой

Заключение

В статье объясняются причины использования определенных методов создания прототипов Web-приложений. Эти методы облегчают разработку Web-дизайна и промежуточного ПО, разбивая ее на две независимые параллельные задачи, что позволяет естественным образом разделить проблемы. Для размещения сайта, даже на этапе разработки, я предпочитаю использовать выделенный Web-сервер, а не СУБД.

В этой статье не освещаются детали аутентификации и авторизации пользователей в CouchDB. После создания прототипа я настраиваю промежуточное ПО для управления пользователями, сеансами и т.п. В зависимости от проекта я могу переложить эти вопросы на CouchDB или использовать специальные инфраструктуры. Я получаю главное – гибкость. Некоторые детали входа и управления сеансами возлагаются на Web-приложение, но это обычно независимый слой.

У меня нет намерения принизить другие подходы к созданию прототипов на платформе NoSQL. Я лишь предлагаю альтернативный подход, заслуживающий внимания. Я хочу показать, насколько продуктивным и удобным может быть объединение наиболее интересных проектов с открытым исходным кодом, использующее их наиболее сильные стороны В процессе работы вы также сможете познакомиться со многими важными деталями, которые в инструментах с тесно связанными слоями зачастую остаются скрытыми.


Загрузка

ОписаниеИмяРазмер
Пример HTML-файла для данной статьиcouchdb-dw.zip9КБ

Ресурсы

Научиться

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

  • Apache CouchDB: загрузите CouchDB.
  • Bootstrap: загрузите Bootstrap.
  • cURL: утилита для Web-тестирования и интеграции сценариев.

Комментарии

developerWorks: Войти

Обязательные поля отмечены звездочкой (*).


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


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

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

 


Профиль создается, когда вы первый раз заходите в developerWorks. Информация в вашем профиле (имя, страна / регион, название компании) отображается для всех пользователей и будет сопровождать любой опубликованный вами контент пока вы специально не укажите скрыть название вашей компании. Вы можете обновить ваш IBM аккаунт в любое время.

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

Выберите имя, которое будет отображаться на экране



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

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

Обязательные поля отмечены звездочкой (*).

(Отображаемое имя должно иметь длину от 3 символов до 31 символа.)

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

 


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


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=40
Zone=Web-архитектура, Open source
ArticleID=960435
ArticleTitle=Создание прототипов Web-приложений с помощью CouchDB и Bootstrap
publish-date=01162014