Веб-разработка с ChicagoBoss framework

    Chicago Boss
    «Chicago Boss — бескомпромиссный веб-фреймворк, любимый дизайнерами, инженерами и этим парнем с пейджером.» — © chicagoboss.org

    «Erlang — язык для создания отказоустойчивых распределенных приложений. Это — один из немногих функциональных языков, который давно и успешно применяется на практике. Например — в телекомах (Ericsson AXD-301 switch), банковских системах, системах автоматизации, высоконагруженных веб-приложениях (Facebook Chat). При этом Erlang — продукт с открытым исходным кодом и распространяется бесплатно.» — говорит нам сайт русскоязычного сообщества Erlang.

    Данный пост предназначен для расширения аудитории Erlang программистов. Если до этого вы считали что функциональное программирование не может быть использовано для бытовых целей, то пора расширить ваш кругозор. Этот пост писался при поддержке моего товарища, лично знакомого с создателем данного фреймворка (Эван Миллер) и последнее время фанатеющего от данного языка.

    По заверению обоих разработка веб-приложений на базе этого фреймворка ничуть не медленнее разработки на тех же рельсах (Ruby on Rails). А в чем-то даже быстрее. Я с функциональным программированием до этого особо знаком не был, но под давлением товарища решил попробовать. Хочу сказать, что опыт был весьма удачным и у меня получилось создать мой первый веб-сайт быстрее, чем год назад с тем же Ruby on Rails.




    Предыстория:
    Дело было в октябре 2010 года на очередном Erlang семинаре, Чикаго, Иллинойс. Под конец лекции произошло следующее (со слов друга): I heard his voice across the room, saying, «I am working on a Rails for Erlang» and 99 people went, «Yeah, right!» (перевод: Я услышал его голос через всю аудитории: «Я работаю над Рельсами для Erlang» и 99 человек сказало «Ага, конечно!»). Звали этого парня Evan Miller. После семинара мой друг расспрашивал его о концепциях и идеях, вложенных в «функциональные рельсы». Идеи ему очень понравились, и с тех пор он все свободное время проводит над проектами с этим фреймворком, а также помогает с документацией Эвану. Он даже организовывал лекции по этому делу и внедрил некоторые вещи у себя в компании.

    1. Вступление
    2. Установка
    3. Настройка рабочей среды (по желанию)
    4. Создание первого проекта
    5. Работа с БД
    6. CRUD
    7. Дополнение
    8. Итоги
    9. Ресурсы


    Вступление


    В этой статье мы сделаем веб сайт, который будет представлять собой адресную книгу (addressbook) с возможностью добавления/удаления/просмотра/редактирования записей. Т.е. реализуем стандартный CRUD.

    Для интересующихся: вся разработка отняла примерно 4-5 часов, включая установку, настройку инструментов и изучение.

    Для достижения поставленной задачи были использованы следующие инструменты:
    Ubuntu 11.10 32bit, Erlang R15B, ChicagoBoss MVC фреймворк, документно-ориентированная база данных MongoDB, Gedit с пакетом плагинов Gmate от iskin (Gedit — это просто текстовый редактор).

    Установка для Mac не сложнее установки для Ubuntu. Для Windows есть отдельная инструкция, но и она от приведенной здесь не особо отличается. Может быть найдутся добрые люди, которые поделятся своим опытом установки для Windows/Mac в комментариях.

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

    Все ссылки на полезные ресурсы, на исходники и на готовый веб сайт в разделе Ресурсы.
    Стоит упомянуть, что сайт находится на моем личном ноуте (Dual-Core CPU T4300 @ 2.10GHz, 2GB). Так что пожалуйста без фанатизма. О падениях (если такие будут) буду сообщать. Предвидя ваш вопрос: запустил я сайт локально, т.к. хотел проверить, при какой нагрузке рухнет сервер. Ну и дешевле получается, чтоб лишний хостинг не покупать. Может кто проявит желание и поделится нормальным сервером, разместим сайт там.
    Если сайт не открывается, значит я химичу с ноутом, попробуйте открыть через пару минут.
    Если какой-то из моментов не понятен, пишите в комментариях, буду править статью.

    Установка


    Erlang

    Для начала нужно установить Erlang последней версии. Идем на этот веб сайт и следуем инструкции для вашей операционной системы. Там же можно скачать нужный дистрибутив или посмотреть необходимый репо.
    У меня Убунту 11.10 32 битная. Для нее дистрибутива нет, только для 64х битной. Поэтому я просто скачал дистрибутив для Убунту 11.04 32 бит. Некоторые фишки в ней не работают, как например графический просмотр существующих потоков и процессов (утилита appmon).



    Но обучению, и даже созданию нормальных проектов, это не мешает.
    Ну и конечно всегда можно собрать нужную версию для своей версии ОС из исходников :) Мой товарищ свои версии уже раз 5 собирал для разных машин: Ubuntu и Mac. Говорит, что конечно геморойно, но вполне возможно за один вечер осилить.

    Еще с проблемами можно обращаться в Erlang-Solutions. Говорят, ребята отзывчивые.

    После скачивания файла и при запуске установки мне выдало следующее:
    installing esl-erlang 1:15.b
    size - 63.8 mb

    После установки для проверки приложения открываем консоль и пишем команду erl. Которая выдает примерно следующее:
    Erlang R15B (erts-5.9) [source] [smp:2:2] [async-threads:0] [hipe] [kernel-poll:false]
    Eshell V5.9

    ChicagoBoss

    Скачать framework можно и без Git, просто зайти на страницу разработки и стянуть последнюю версию.

    Устанавливаем Git, если его у вас еще нет:
    apt-get install git-core
    получаем копию ChicagoBoss framework:
    git clone git://github.com/evanmiller/ChicagoBoss.git

    Заходим в дирректорию вашего репо:
    cd ChicagoBoss
    Компилируем:
    ./rebar get-deps clean compile

    Чтобы завести новый проект (нужно находится в дирректории нашего фреймворка):
    make app PROJECT=your_project_name_here
    Затем:
    cd ../your_project_name_here

    Для запуска дебаг (developer) режима:
    ./init-dev.sh
    Для запуска в продакшн:
    ./init.sh start

    Дождитесь, пока сообщения перестанут двигаться. Если отчетов об ошибках или крешах нет, то можно открывать localhost:8001
    Теперь можно создавать новые модели, контроллеры, вьюшки и сразу смотреть результат без перекомпиляции и перезапуска сервера. В некоторых случаях перекомпиляция все-таки нужна, например когда меняете маршруты (routes).
    Компиляция вызывается командой:
    ./rebar compile

    ChicagoBoss по умолчанию использует веб-сервер на Misultin и при создании приложения в конфиге прописывается порт 8001. При желании сервер можно заменить на Mochiweb, а возможно и на Cowboy.

    MongoDB

    Тут все очень просто. Качаем и устанавливаем. В Убунту вобще только одна команда:
    apt-get install mongodb

    Для проверки работоспособности можно ввести одну из команд в консоль:
    mongo
    или
    ps aux | grep mongo
    А также можно попробовать постучаться по адресу localhost:28017. Родной порт, по которому приложения обычно работают с Монго — 27017. Для браузера по умолчанию используется 28017.

    Для управления MongoDB сервером используются следующие команды:
    $ sudo status mongodb
    $ sudo stop mongodb
    $ sudo start mongodb
    $ sudo restart mongodb

    После некорректного выключения сервера, например, при выключении/перезагрузке машины, при старте сервера БД он все равно остается выключенным. Сделано это специально созданием lock файла. Чтобы запустить сервер снова нужно сделать следующее:
    1. Удалить lock файл
    2. Запустить скрипт восстановления

    $ sudo rm /var/lib/mongodb/mongod.lock
    $ sudo -u mongodb mongod -f /etc/mongodb.conf --repair

    Ну вот собственно и все, мы готовы к созданию наших собственных приложений. По большому счету приложения создавать можно и без базы данных, либо использовать другую БД. На ваше усмотрение. Поддерживаемые БД перечислены в документации.

    Настройка рабочей среды (по желанию)


    Я скачал пакет плагинов Gmate. Из них реально использую пока только Zen Coding. Отличное пособие по использованию этого плагина представлено в этой видео лекции. Реально упрощает жизнь.
    Один мой друг сказал что это HAML для бедных, но меня использование этой прослойки пока «не вставляет».
    И еще использую сниппеты (Snippets). Этот плагин поставляется с Gedit, но по умолчанию он выключен. Для включения идем Edit -> Preferences -> Plugins -> Snippets.
    Он прост в использовании, просто открываете Tools -> Manage Snippets -> «your_language» и редактируете существующие или добавляете свои сниппеты. Инструкция по работе с ними находится здесь. У меня на их разбор ушло минуты 3 и потом еще минут 15 на создание своих собственных. Зато как удобно потом написать что-то типа div, нажать на Tab и получить следующее:
    <div>
    
    </div>
    

    А при желании можно еще текста добавить, например дополнительных полей id, style и т.д. А также поставить значения по умолчанию и точки, куда курсор будет прыгать при следующем нажатии Tab.
    Я работал со сниппетами в Visual Studio, ИМХО в Gedit с ними работать гораздо удобнее.

    И да, подобные плагины есть для Emacs, Notepad++ и еще для кучи других редакторов.

    Создание первого проекта


    Все поставлено, все работает. Можно приступать к созданию своего веб-сайта. Заходим в дирректорию с ChicagoBoss и пишем команду:
    make app PROJECT=addressbook

    Да, названием проекта должен быть валидный атом. Атом — это именованная константа. Начинаться название должно только с маленькой буквы, название может содержать только буквы, цифры и символ подчерка.

    Фреймворк создает новую директорию, по-умолчанию в домашнем каталоге. Весь проект находится внутри, если возникнет желание переместить/передать кому-то/удалить проект, достаточно будет манипуляций с этим каталогом. Переходим во вновь созданную директорию нашего проекта
    cd ../addressbook

    Весь наш код/ресурсы лежат в каталоге src. Общая структура:


    Структура каталога src:

    Файлы ресурсов (javascript, css, медиафайлы) лежат в /priv/static/. Подключение файла стилей будет выглядеть так:
    <link rel="stylesheet" href="/static/css/style.css" type="text/css" charset="utf-8" />


    Редактируем boss.config, добавляем данные о БД:
    {db_host, «localhost»},
    {db_port, 27017},
    {db_adapter, mongodb},
    {db_database, addressbook},
    {db_write_mode, safe},
    {db_read_mode, master},

    Вот так выглядит мой конфиг (и вобще окружающая среда):


    Я в первый раз слово addressbook неправильно написал, пришлось потом приложение пересоздавать с правильным именем, потому что к имени привязано многое.

    Далее создаем файл address.erl в src/model/. Он нужен для доступа к БД. У меня он выглядит так:
    -module(address, [Id, Firstname, Lastname, Address1, Address2, City, State, Country, Active, CreationTime, ModifictionTime ]).
    -compile([export_all]).


    Cоздадим контроллер с именем addressbook_main_controller.erl (appname_controllername_controller) и напишем внутри такой код:
    -module(addressbook_main_controller, [Req, SessionID]).
    -compile([export_all]).
    
    index('GET', [])->{ok, [{data, "Hello World"}]}.


    index — это наша функция,
    все что находится после "->" является телом функции.
    Эта функция будет реагировать на запрос GET и при удачной обработке вернет нашу строку в переменной data.
    ok — означает что все прошло хорошо. Для обработки ошибки используется слово error. Выглядеть это может так:
    index('GET', [])->
    	{ok, [{data, "Hello World"}]};
    	{error, Reason}->
    			Reason.
    


    Для того чтобы отобразить вернувшееся значение на странице, в нашей вьюшке нужно будет добавить тег {{data}}. Для проверки создадим наш первый html файл в каталоге /src/view/main/. Назовем его index.html:
    <!DOCTYPE html>
    <html>
      <head>
        <meta charset="utf-8" />
        <title>My addressbook</title>
      </head>
      <body>
        <form>
          <div id="main">
    	  {{data}}
          </div>
        </form>
      </body>
    </html>
    


    Последний штрих заключается в настройке маршрутов. Открываем файл /priv/addressbook.routes и дописываем наш новый маршрут (по умолчанию у нас еще нет ни одного маршрута, все строки закомментированы):
    {"/", [{controller, "main"}, {action, "index"}]}.

    Компилируем наше приложение ./rebar compile
    И запускаем ./init-dev.sh

    Если теперь перейти в браузер и открыть localhost:8001, можно будет увидеть наш Hello World.
    Все последующие изменения, за исключением изменения маршрутов, будут применены без перекомпиляции и перезапуска сервера, т.е. на лету.

    Про маршруты: можно жестко указать, при каком адресе какой контроллер и метод вызывать. Либо можно в адресе задавать полный путь вида /[controller name]/[action name]. Т.е. в нашем случае у нас есть контроллер с именем main. Если мы добавим в наш контроллер новый метод с именем create, то вызвать его можно будет, обратившись по адресу localhost:8001/main/create. Либо указав следующий маршрут:
    {"/create", [{controller, "main"}, {action, "create"}]}.

    И тогда вызов будет выглядеть как localhost:8001/create

    Работа с БД


    Подключение к нашей БД уже состоялось. Вы даже можете выполнять запросы в консоли во время работы веб-сервера. Для этого достаточно перейти в консоль, где мы выполнили команду запуска приложения ./init-dev.sh, нажать, например, Ввод и в новой открытой строчке ввести, например это:
    boss_db:find(address, []).


    Данная команда выводит все записи, привязанные к модели address. Сейчас там нет ни одной записи (или есть пустая по-умолчанию).
    Вы можете ввести boss_db: нажать Tab и посмотреть доступные команды.

    [] — означает «параметры». Если внутри скобок пусто, значит вы передаете 0 параметров. В случае с командой find можно получить список записей, у которых firstname=«ivan»:
    boss_db:find(address, [{firstname, "ivan"}]).

    В консоли можно выполнять множество полезных команд, и не только с БД.

    CRUD


    И так, наша модель готова к работе, теперь в контроллере можно добавлять новые функции. Добавим функцию create, которая будет добавлять новые записи:
    create('GET', [])->ok;
    create('POST', [])->
    	Firstname = Req:post_param("firstname"), 
    	Lastname = Req:post_param("lastname"), 
    	Address1 = Req:post_param("address1"), 
    	Address2 = Req:post_param("address2"), 
    	City = Req:post_param("city"), 
    	State = Req:post_param("state"), 
    	Country = Req:post_param("country"), 
    	Active = Req:post_param("active"), 
    	CreationTime = erlang:now(), 
    	ModificationTime = erlang:now(),
    	NewAddress = address:new(id, Firstname, Lastname, Address1, Address2, City, State, Country, Active, CreationTime, ModificationTime),
    	case NewAddress:save() of
    		{ok, SavedAddress}->
    			{redirect, [{action, "index"}]};
    		{error, Reason}->
    			Reason
    	end.
    


    Я думаю прочитать код для программиста не составляет труда, поэтому объяснять я тут ничего не буду. Единственное что могу сказать, что id создается автоматом.
    id — зарезервированное слово.
    Id — так можно назвать вашу переменную.
    Да, язык регистрозависимый.

    Теперь создадим html файл для этого метода. Назовем его create.html:
    <!DOCTYPE html>
    <html>
       <head>
          <title>My addressbook</title>
       </head>
       <body>
       <form method="post">
         <header></header>
         <div id="main">
           <table>
             <tr><td>Frist name</td>
               <td><input type="text" id="firstname" name="firstname" size="45" maxlength="255" value="" /></td></tr>
             <tr><td>Last name</td>
               <td><input type="text" id="lastname" name="lastname" size="45" maxlength="255" value="" /></td></tr>
             <tr><td>Address1</td>
               <td><input type="text" id="address1" name="address1" size="45" maxlength="255" value="" /></td></tr>
             <tr><td>Address2</td>
                    <td><input type="text" id="address2" name="address2" size="45" maxlength="255" value="" /></td></tr>
                <tr><td>City</td>
                    <td><input type="text" id="city" name="city" size="45" maxlength="255" value="" /></td></tr>
                <tr><td>State</td>
                    <td><input type="text" id="state" name="state" size="45" maxlength="255" value="" /></td></tr>
                <tr><td>Country</td>
                    <td><input type="text" id="country" name="country" size="45" maxlength="255" value="" /></td></tr>
                <tr><td>Active</td>
                    <td><input type="checkbox" id="active" name="active" value="true" /></td></tr>
             </table>
    
             <button type="submit">Submit</button>
          </div>
       </form>
       </body>
    </html>
    


    Тут важно отметить, что для наших контролов, которые передают значения, нужно указывать и id и name параметры. Каждый из них используется разными частями фрэймворка. По-моему Эван это дело хочет пофиксить и оставить только один обязательный параметр. Кстати, обновления выходят довольно часто, чуть ли не каждую неделю, так что не исключено что к моменту публикации этой статьи фикс уже будет выпущен.

    Добавим еще одну функцию для просмотра всех записей в нашей базе (точнее заменим написанную ранее функцию index):
    index('GET', [])->Addresses = boss_db:find(address, []),
    	{ok, [{addresses, Addresses}]}.
    


    Также поменяем код нашей index.html страницы:
    <!DOCTYPE html>
    <html>
      <head>
        <meta charset="utf-8" />
        <title>My addressbook</title>
      </head>
      <body>
        <form method="post">
          <header></header>
          <div id="main">
    	<table cellspacing="0" cellpadding="0">
    		<tr>
    			<th>First name</th>
    			<th>Last name</th>
    			<th>City</th>
    			<th>Address1</th>
    			<th>Address2</th>
    			<th>State</th>
    			<th>Country</th>
    			<th>Active</th>
    		</tr>
    		{% if addresses %}
    			{% for address in addresses %}
    				<tr>
    					<td>{{address.firstname}}</td>
    					<td>{{address.lastname}}</td>
    					<td>{{address.city}}</td>
    					<td>{{address.address1}}</td>
    					<td>{{address.address2}}</td>
    					<td>{{address.state}}</td>
    					<td>{{address.country}}</td>
    					<td>{{address.active}}</td>
    				</tr>
    			{% endfor %}
    		{% endif %}
    	</table>
          </div>
        </form>
      </body>
    </html>
    


    ChicagoBoss использует систему шаблонов Django, через библиотеку ErlyDTL. The Django Template language.

    Теперь при обращении по адресам /main/ и /main/create вы получите 2 формы: с вводом и выводом информации из БД.

    Для удаления (delete) записи будет достаточно следующей функции в нашем контроллере:
    delete('GET', [Id])->
    	boss_db:delete(Id),
    		{redirect, [{action, "index"}]}.
    

    Остается только его вызвать localhost:8001/main/delete/[id]

    Для отображения записи (show), добавим в контроллер эту функцию:
    show('GET', [Id])->
    	Address = boss_db:find(Id),
    		{ok, [{address, Address}]}.
    


    Создадим view файл show.html:
    <!DOCTYPE html>
    <html>
       <head>
          <title>My addressbook</title>
       </head>
       <body>
       <form method="post">
    		<div id="main">
    			<table cellspacing="0" cellpadding="0">
    			{% if address %}
    			<tr><td>First name</td><td>{{address.firstname}}</td></tr><tr>
    				<td>Last name</td><td>{{address.lastname}}</td></tr><tr>
    				<td>City</td><td>{{address.city}}</td></tr><tr>
    				<td>Address1</td><td>{{address.address1}}</td></tr><tr>
    				<td>Address2</td><td>{{address.address2}}</td></tr><tr>
    				<td>State</td><td>{{address.state}}</td></tr><tr>
    				<td>Country</td><td>{{address.country}}</td></tr><tr>
    				<td>Modification time</td><td>{{address.modification_time}}</td></tr><tr>
    				<td>Creation time</td><td>{{address.creation_time}}</td></tr><tr>
    				<td>Active</td><td>{{address.active}}</td></tr>
    			{% endif %}
    			</table>
    		 </div>
        </form>
      </body>
    </html>
    


    Редактирование записи — это смесь create и show. Добавим еще две функции в наш контроллер:
    edit('GET', [Id])->
    	Address = boss_db:find(Id),
    		{ok, [{address, Address}]};
    
    edit('POST', [Id])->
    	Address = boss_db:find(Id),
    	NewAddress = Address:set([{firstname, Req:post_param("firstname")}, {lastname, Req:post_param("lastname")}, {address1, Req:post_param("address1")}, {address2, Req:post_param("address2")}, {city, Req:post_param("city")}, {state, Req:post_param("state")}, {country, Req:post_param("country")}, {active, Req:post_param("active")}, {modification_time, erlang:now()}]),
    	case NewAddress:save() of
    	{ok, SavedAddress}->
    		{redirect, [{action, "index"}]};
    	{error, Reason}->
    		Reason
    	end.
    

    Важно отметить, что в Erlang все переменные — неизменны! Поэтому сначала приходится получать Address, а затем измененное состояние этой переменной присваивать NewAddress.
    Первая функция делает тоже самое, что и функция show, вторая обновляет информацию в БД после нажатия кнопки Submit в форме.
    Добавляем эту самую форму edit.html:
    <!DOCTYPE html>
    <html>
       <head>
          <title>My addressbook</title>
       </head>
       <body>
       <form method="post">
    		<table cellspacing="0" cellpadding="0">
    		{% if address %}
    			<tr><td>First name</td><td><input type="text" id="firstname" name="firstname" size="45" maxlength="255" value="{{address.firstname}}" /></td></tr><tr>
    				<td>Last name</td><td><input type="text" id="lastname" name="lastname" size="45" maxlength="255" value="{{address.lastname}}" /></td></tr><tr>
    				<td>City</td><td><input type="text" id="city" name="city" size="45" maxlength="255" value="{{address.city}}" /></td></tr><tr>
    				<td>Address1</td><td><input type="text" id="address1" name="address1" size="45" maxlength="255" value="{{address.address1}}" /></td></tr><tr>
    				<td>Address2</td><td><input type="text" id="address2" name="address2" size="45" maxlength="255" value="{{address.address2}}" /></td></tr><tr>
    				<td>State</td><td><input type="text" id="state" name="state" size="45" maxlength="255" value="{{address.state}}" /></td></tr><tr>
    				<td>Country</td><td><input type="text" id="country" name="country" size="45" maxlength="255" value="{{address.country}}" /></td></tr><tr>
    				<td>Active</td><td><input type="checkbox" id="active" name="active" value="{{address.active}}" /></td></tr>
    		{% endif %}
    		</table>
    		<button type="submit">Submit</button>
    	</form>
      </body>
    </html>
    

    Ну вот собственно и все, наш CRUD готов.

    Дополнение


    Пока писал статью, успел прикрутить логин, регистрацию, список зарегистрированных пользователей, чат, валидацию ввода, а также админку (весь код сайта лежит на github, ссылка в разделе Ресурсы).

    Чат без всяких наворотов, исключительно для теста и все еще содержит баги, особенно при работе под IE, поэтому специально для него я запретил логин, иначе он вызывает некоторые проблемы. Чатиться с ним можно, сервер не падает, но не комфортно. У меня задача показать работу Erlang, а не проблемы Ajax в IE решать.

    Админку можно установить на любой новый сайт, там работы минут на 5.

    А также поигрался с шаблонами. В итоге у меня получился один мастер-шаблон, который выглядит вот так:
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <link rel="stylesheet" href="/static/css/style.css" type="text/css" charset="utf-8" />
        <title>{% block title %}My amazing site{% endblock %}</title>
        {% block res %} {% endblock %}
    </head>
    
    <body>
       <header>
    		{% if person %}
    			Hello, {{person.name}}
    			(<a href="/user/logout">Quick, Log Me Out!</a>)
    			<br />
    		{% endif %}
    		Your IP: {{ip}}
    	</header>
    	<nav>
    		<ul class="nav">
    			<li class="nav"><a href="/">Home</a></li>
    			<li class="nav"><a href="/create">Create</a></li>
    			<li class="nav"><a href="/chat/live/public">Chat</a></li>
    			<li class="nav"><a href="/user/login">Login</a></li>
    			<li class="nav"><a href="/user/showall">Users</a></li>
    		</ul>
    	</nav>
    	<section>
    	  {% block content %}{% endblock %}
    	</section>
    	<footer>
    	   {% block footer %}{% endblock %}
    	</footer>
    </body>
    </html>
    

    И вот так теперь выглядит мой show.html:
    {% extends "layout/application.html" %}
    
    {% block title %}My addressbook{% endblock %}
    {% block content %}
    	<table cellspacing="0" cellpadding="0">
    	{% if address %}
    		<tr><td>First name</td><td>{{address.firstname}}</td></tr><tr>
    			<td>Last name</td><td>{{address.lastname}}</td></tr><tr>
    			<td>City</td><td>{{address.city}}</td></tr><tr>
    			<td>Address1</td><td>{{address.address1}}</td></tr><tr>
    			<td>Address2</td><td>{{address.address2}}</td></tr><tr>
    			<td>State</td><td>{{address.state}}</td></tr><tr>
    			<td>Country</td><td>{{address.country}}</td></tr><tr>
    			<td>Modification time</td><td>{{address.modification_time}}</td></tr><tr>
    			<td>Creation time</td><td>{{address.creation_time}}</td></tr><tr>
    			<td>Active</td><td>{{address.active}}</td></tr>
    	{% endif %}
    	</table>
    {% endblock %}
    

    Получается один каркас и разный контент.
    Подробнее о Django шаблонах можно почитать на официальном сайте, ссылка есть в Ресурсах ниже.

    Еще ChicagoBoss имеет в своем арсенале свои собственные шаблоны. Немного ниформации о них можно найти на официальном сайте. Там ничего сложного нет. Просто замена часто используемого кода тегами. Ну и еще некоторые плюшки.

    Итоги


    Здесь будут итоги работы сервера по прошествии двух дней.

    UPD: На данный момент из итогов только следующее:
    Сайт делался без какой-либо защиты от инжектов, без цели провести security проверку. Сайт делался только чтобы показать пример работы технологий на простых примерах.

    UPD: Хабраэффект наблюдался только на 30ое марта. В остальные дни посетивших пользователей можно посчитать по пальцам.
    Согласно Google Analytics и моим локальным логам за день:
    — сайт посетило 1489 пользователей
    — просмотров страниц — 9070
    — запросов к БД — 43051
    — максимальное кол-во пользователей в чате одновременно ~100

    Запросов могло быть больше, если бы чат не положили никами с джаваскрипт кодом.

    За все время сервер ни разу не упал. Приходилось выключать только для чистки БД от вредных имен и для того чтобы добавить хоть какую-то защиту от мародеров.

    Ресурсы


    Ссылка на тестовый сайт
    Ссылка на исходники

    Официальный веб-сайт ChicagoBoss. На этом же сайте вы найдете API документацию, ссылки на Wiki, обучение работы с фреймворком.
    Официальный веб-сайт Erlang
    Русское сообщество Erlang. Там же находится русская Wiki.
    Отличный сайт для изучения Erlang
    Erlang документация
    Erlang solutions. Отсюда можно скачать нужную версию Erlang.

    Обучающее видео от Эвана: эпизод 1, эпизод 2, эпизод 3
    Конкурентное программирование с Erlang. Хороший видео материал для обучения.

    Различия между Ruby on Rails и ChicagoBoss
    Сравнение Nodejs и Erlang
    How to serve a million users!

    The Django Template language. Система шаблонов Django.

    ChicagoBoss Google Group
    Поделиться публикацией

    Похожие публикации

    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

    Подробнее
    Реклама

    Комментарии 57

      +4
      Большая статья. Побольше бы на Хабре таких.
      • НЛО прилетело и опубликовало эту надпись здесь
        +2
        Отличная статья. Давно хотел пощупать erlang, а тут такой шанс :)

        PS. Что мне нравится в django — так это его шаблоны. Очень к ним привык. И их поддержка — весомый аргумент.

        И да, labs.evolope.com/ у меня не загружается.
          0
          Спасибо. Про labs.evelope.com — правда, еще несколько дней назад открывался, там хорошо так все с графиками расписано было. Теперь сайт лежит.
            0
            В кеше гугла осталось.
          0
          Сайт сравнения не работает.
            0
            Об именовании проекта: именем должен быть валидный атом.
              0
              Большое спасибо за статью, классный фреймворк.
              • НЛО прилетело и опубликовало эту надпись здесь
                  0
                  Адепты отвечают, что лучше :) Особенно когда речь идет о распределенной системе. Мой опыт пока основывается только на сайте из топика.
                  5 часов работы — полет нормальный. Я даже на ходу код менять успевал.
                    +2
                    А что у него было не так с производительностью?
                    • НЛО прилетело и опубликовало эту надпись здесь
                        0
                        Зачем холивар, хотелось бы узнать, что именно у него не так с производительностью.

                        HiPe появился, как исследовательский продукт. И?
                        • НЛО прилетело и опубликовало эту надпись здесь
                            +3
                            Нет, не буду. ТОлько вот сфуровакуумная производительность даром никому не сдалась.

                            Например, Erlang гарантирует soft realtime. Это достаточно производительно? А вот опять хз — это сферовакуум.

                            При этом Erlang прекрасно себя чувствует там, где PHP/Python/Ruby даром никому не сдались — управление диким количеством процессов на в распределенных системах ;)

                            Так что с производительностью у него все более, чем в порядке :)
                              +2
                              Можете посмотреть вот на этот старый бенчмарк, где Erlang по скорости идет сразу за С, а после него уже Ruby, PHP, JS.

                              Либо вот на этот новый, где Erlang также во многих тестах работает быстрее Ruby 1.9. Причем Erlang способен работать на всех выданных ему ядрах сразу и можно руками задавать, сколько процессов или памяти он максимально может использовать.

                              А если брать компиляцию Erlang HiPe, то получается еще быстрее.
                      0
                      Статья очень хорошая, но все же. Добавили быть хоть фильтрацию форм. Теги прикручиваются на раз, SQL команды не проверял.
                        0
                        Ну SQL в монго и нет, а про какие теги речь идет? Вы их прикручивали только в своем браузере или как-то смогли повлиять на сервер или на других участников чата?

                        Ну и добавлю, что клиента вылизывать мне совсем не хотелось. Да и серверную часть в реальном приложении надо было бы дописывать. А поскольку приложение тестовое, то и код должен быть легко читаемым и понятным и времени на него как правило очень много не тратится. Хотя даже это тестовое приложение уже неплохо функционирует без ошибок в течении 8ми часов.
                          0
                          Теги?
                          <script>window.location.href="http://site.ru"</script>
                          


                          Я полностью согласен, что в тестовом приложении над многими вещами заморачиваться не нужно, но все же, если Вы не фильтруете теги, то банально вставив такие строчки в любое из полей никто не увидит Вашего приложения.
                          С уважением
                            0
                            Я думал разговор про чат идет, в базовой форме да, ничего не фильтрую, надо будет добавить, спасибо.
                        +6
                        В hello world все феймворки хороши, самое интересное начинается, когда проект перевалит ну хотя бы за 10.000 строк, из которых ну пусть 40% будет занимать задник.

                        Erlang действительно может хорошо себя проявить в типичной для эрланга среде — небольших модулях приложений, где критично важна быстрая маршрутизация, поддержка кучу соединений отовсюду, realtime и т.д. Но если речь идет о сложных моделях, сложных формах, многообразии данных и большом количестве преобразований текста — это не для эрланговских проектов.
                        То есть все возможно, но затраты на разработку и поддержку будут неадекватными.

                        Этот фреймворк, честно говоря, как раз и предлагает этот сомнительный подход, ну нафига ему шаблонизация, формы и прочие слабые стороны, куда логичнее если ss на эрланге обслужавает json/xml API для современной динамической морды на js фреймворках.
                        • НЛО прилетело и опубликовало эту надпись здесь
                            0
                            Раз уж вы здесь написали: это известная ошибка, и проявляется, если галочку при создании адреса поставить. Я условие неверно составил. Буду править утром, у меня ночь.
                              0
                              Добавил быстрофикс, больше не падает.
                            0
                            create('GET', ...

                            Странно, почему не атом, а строковое, ради наглядности, чтобы большими буквами?
                              0
                              Это и есть атом :)
                                0
                                Подзабыл синтаксис.
                              0
                              Стоит упомянуть ещё Nitrogen и Webmachine.
                              Было бы также из целей уважения к Erlang честнее использовать Riak вместо Mongo.
                                +1
                                Все что крутится вокруг эрланга, это выбор. Даже сами создатели риака очень часто советуют, берите не ради уважения, а то, что вам подходит. Подходит монга, ок, значит монга. Кстати офф. драйвер для монги из эрланга так себе, есть что-то около трех разных реализаций, есть у кого какой опыт в этом?
                                  0
                                  Не надо руководствоваться уважением. Например, для Metalkia я взял Riak, но только потому, что не хотел сразу сидеть обдумывать схему базы данных. После некоторого времени схема устоялась, и параллельно появилось несколько мест, из-за которых использование реляционной СУБД было бы намного удобнее. Всякий NoSQL хорош только как KV-хранилище, когда не надо делать сложных запросов. В подавляющем большинстве случаев лучше брать MySQL или PostgreSQL и не слушать хипсторский хайп.
                                    0
                                    Вообще-то, если задуматься, то MongoDB, использованный в статье аналогично Riak принадлежит к категории NoSQL, так что я вовсте не кричу «используй NoSQL или лох».
                                    Вообще-то, если задуматься, ChicagoBoss тоже хипстерский хайп, и двойной хипстерский хайп статью бы не ухудшил, тем более, что про практику работы с Riak на хабре никто ещё и не писал.
                                    Для дисклеймера скажу, что в подавляющем большинстве моих проектов тоже используется именно Postgres, а схема постепенно устаканивается миграциями.
                                  0
                                  на главной странице тестового сайта выскакивает окно яваскрипта со «словом из трех букв». так и должно быть?
                                    +1
                                    Это фича.
                                      +1
                                      Это хабражители постарались. Я свой ноут на растерзание для проверки производительности оставил, проверить, выдержит ли хабраэффект, вместо этого добрые люди запостили скриптов во все возможные формы, после чего все формы стали показывать всякие алерты и редиректиться на разные сайты. И проверка производительности пошла ко дну, т.к. все формы перестали корректно работать.
                                      Они конечно молодцы, мозгов много, девать некуда. Умеют js и html инжекты делать. Только вот никто и не говорил что сайт супер защищенный или вобще хоть какая-то защита встроена. Были голые формы для уменьшения и упрощения кода, чтобы людям удобнее его понимать было.
                                      0
                                      А вот этот ручной разбор аргументов в request — это так и надо?
                                        0
                                        Автоматизировать/оптимизировать можно что угодно. Пока что я другого способа получения параметров из формы не знаю.
                                        0
                                        Почему записи удаляете как GET /main/delete/id, а не DELETE /resrource/id? Ну хотя бы POST с csrf_token что ли… Молодец, что показали что и как, но если уж показывать, то правильно.
                                          0
                                          Я не автор, но прокомментирую. Тут в принципе не REST демонстрировался, но в любом случае такие действия по GET не делаются, тут я с вами согласен.
                                            0
                                            С GET было проще и быстрее сделать. В данном случае мне только нужно перейти по ссылке, которая приведет меня к нужной функции в контроллере и передаст параметр. Для этого простой ссылки-иконки достаточно.
                                            Надеюсь, что люди понимают, что на самом деле там разные запросы могут быть и какой в каком случае нужно использовать.
                                            0
                                            Как в Erlang дела обстоят с поддержкой utf-8?
                                              +1
                                              Если делать только I/O или конвертацию между кодировками, то без проблем.

                                              Хитрые манипуляции с текстом провести не получится, для этого
                                              github.com/freeakk/ux
                                              github.com/freeakk/i18n
                                                0
                                                i18n в ChicagoBoss поддерживается, там с этим просто.
                                                  0
                                                  Это другой i18n ;)
                                              0
                                              Название фреймворка впечатляющее
                                                0
                                                А alert «2 Х У Я» при переходе по ссылке и редирект на ya.ru — это так и задумано? :)
                                                  0
                                                  Ответ здесь. И еще апдейт в разделе Итоги.
                                                  +3
                                                  Стоит упомянуть, что сайт находится на моем личном ноуте

                                                  Можно же на Heroku задеплоить используя, например, этот билдпак? Бесплатно причем.
                                                    0
                                                    Можно попробовать. Через пару дней после тестов.
                                                    0
                                                    Для тех, кому хоть сколько-то интересен Erlang, можно взглянуть на Elixir.
                                                      +1
                                                      Конфиги в эрланг-стиле – издевательство над администраторами. В обилии скобочек легко запутаться.
                                                      YAML для описания конфига БД и роутов подошел бы гораздо больше (см. рельсы), но этот язык так и не прижился у эрлангеров, даже тех, кто занимается вебом.

                                                      Еще поражает обильное использование параметризованных модулей. Это, вероятно, добро, но может несколько затруднить дебаг.

                                                      -module(address, [Id, Firstname, Lastname, Address1, Address2, City, State, Country, Active, CreationTime, ModifictionTime ]).
                                                      address:new(id, Firstname, Lastname, Address1, Address2, City, State, Country, Active, CreationTime, ModificationTime),
                                                      Здесь лучше использовать рекорды – так будет более читаемо и менее затратно при изменении структур.
                                                        0
                                                        Фишка конфига в простом описании типов данных. Если нужен атом, то это он и будет.

                                                        С остальным согласен. Иногда даже кажется, что у этого фрейворка больше общего с рельсами, чем с Erlang. Кажется это потому, что в Erlang не принято смешивать данные (даже просто схему данных) и код. Эдакое ООП наоборот.

                                                        address:new(id, Firstname, Lastname, Address1, Address2, City, State, Country, Active, CreationTime, ModificationTime)

                                                        Это чудо очень спорно и пришло к нам из ErlyWeb. Там new(Fields) был одним из способов описания новой записи.
                                                        На вопрос, что будет, если переставить поля в определении записи, ответ прост: надо перелапатить весь клиентский код :(
                                                        Гораздо проще было бы:
                                                        #address{first_name=Name}
                                                        0
                                                        Спасибо за статью. Хотел спросить, существует ли готовый модуль для аутентификации?
                                                          0
                                                          Готовые функции авторизации и аутентификации есть в модулях news и mail. А также есть сторонние примеры, простые примеры работы с куками, логин, регистрация есть в моем коде на гитхабе.

                                                          Еще нашел вот этот модуль: github.com/alex-marandon/chicagoboss_who
                                                          Выглядит неплохо, можно использовать.
                                                          0
                                                          Спасибо за статью, давно хотел посмотреть на Chicago Boss, да так и не посмотрел до сих пор. Сам делал вебню на Nitrogen (Metalkia).
                                                            0
                                                            А виджеты как-то можно делать в ChicagoBoss? Типа список последних новостей/продуктов в боковой колонке. То что находится в /src/view/lib как я понял позволяет либо только шаблон подключить своим тегом, либо только функцию. А так чтобы это было похоже на контроллер который сам получит данные и отдаст их в шаблон?

                                                          Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                                                          Самое читаемое