От переводчика: «Elixir и Phoenix — прекрасный пример того, куда движется современная веб-разработка. Уже сейчас эти инструменты предоставляют качественный доступ к технологиям реального времени для веб-приложений. Сайты с повышенной интерактивностью, многопользовательские браузерные игры, микросервисы — те направления, в которых данные технологии сослужат хорошую службу. Далее представлен перевод серии из 11 статей, подробно описывающих аспекты разработки на фреймворке Феникс казалось бы такой тривиальной вещи, как блоговый движок. Но не спешите кукситься, будет действительно интересно, особенно если статьи побудят вас обратить внимание на Эликсир либо стать его последователями.» В этой части речь больше пойдёт о вёрстке, чем непосредственно об Эликсире, однако статья будет полезна тем, что расскажет о взаимодействии с ассет-пайплайном Phoenix. Вы можете прямо сейчас открыть первую часть и за несколько вечеров создать работающее приложение на Фениксе и посмотреть на Эликсир в действии. А также познакомиться с вебсокетами, плагами, ченджсетами и другими страшными словами функциональной веб-разработки :) В прошлой части мы закончили с написанием тестов для всего, связанного с каналами. На этот раз будет значительно меньше кода на Elixir, вместо которого мы научимся использовать сторонние библиотеки внутри Phoenix-приложений. Как правило, Phoenix встречает вас с очень-очень базовой версией Bootstrap, оптимизированной под него. Давайте немного отойдём от этого подхода и заменим его на другой CSS-фреймворк (а также будет использовать Sass).  Предупреждение. Автор статьи точно не является дизайнером. Результат может вас напугать, так что попробуйте менять всё на свой вкус.  Не хотелось бы начинать спор на тему Bootstrap против Foundation. Вместо этого давайте просто возьмём Foundation, потому что внешний вид сайта на нём выглядит интереснее. Также для него нужно делать чуть меньше шаблонных вещей, по сравнению с Bootstrap. Кроме того, не так много людей пробовали использовать Foundation, так что будет тем интереснее! Примечание. Обратите внимание, что для избежания проблем совместимости jQuery и Foundation, здесь устанавливается конкретная версия jQuery (v2.2.4). Для дополнительной информации посмотрите эту статью. Также нужно поправить brunch-config.js, чтобы учесть изменения. А именно подключение Foundation к Brunch, включая загрузку Sass-директорий, конфигурацию модуля Sass, и установка jQuery в качестве глобальной зависимости для Npm. Затем, нам нужно добавить директорию для Sass-файлов. Создайте директорию web/static/scss с 3 файлами внутри: В файл web/static/scss/application.scss добавьте: В файл web/static/scss/_settings.scss добавьте содержимое файла по ссылке. В файл web/static/scss/_custom.scss добавьте: Вам также потребуется загрузить картинку и кинуть его в директорию web/static/assets/images/computer-bg.png, чтобы файл стилей мог использовать его в качестве фонового изображения. Если вы захотите подключить шрифт с иконками из набора Foundation, выполните следующие шаги: Теперь иконки должны быть полностью установлены. Откройте файл web/static/css/phoenix.css и удалите всё, что в нём есть! Нам ничего из этого не понадобится, но могло бы пригодиться, если бы мы решили использовать стандартный CSS. Перед тем как продолжить, хотелось бы сделать ещё одну вещь – улучшить написанный ранее код. Например, способ работы с текущим пользователем немного ненадёжен и требует писать один и тот же код снова и снова. Давайте добавим коду, связанному с текущим пользователем, возможность повторного использования. Сначала создадим новый плаг, который расположим в файле web/controllers/current_user_plug.ex: Что здесь происходит? Сначала импортируется Plug.Conn внутрь нашего модуля (так что можно легко получить доступ к функциям assign и get_session). Далее описывается функция init, принимающая и тут же возвращающая переменную default. Самая суть плага находится в функции call. Любой плаг должен реализовывать две функции – init и call. Функция call должна принимать conn и необязательные опции, а возвращать conn (изменённый или нет). Если current_user есть в текущей сессии, то достаём его и закидываем внутрь conn, чтобы можно было отовсюду получать доступ к текущему пользователю. Если достать его нельзя, то просто возвращаем неизменённый conn. Затем, чтобы использовать плаг current_user глобально, откройте файл web/router.ex и вставьте его в стандартный пайплайн браузера: Вот и всё! Теперь, когда потребуется обратиться к текущему пользователю внутри разметки, мы можем просто вызвать @conn.assigns[:current_user]. Замечательно! Приступаем к рефакторингу основного макета приложения, чтобы было проще вносить изменения и легче повторно использовать общие элементы. Начнём с раздела head (всё что между тегами <head>). Создайте файл web/templates/layout/head.html.eex  и перенесите в него тег head вместе с содержимым: По большей части мы просто скопировали контент тега head, но при этом немного упростили работу с текущим пользователем и добавили немного информации в теги description, author и title. Вместо предыдущего подхода, когда использовался хелпер из LayoutView, теперь проверяется есть ли current_user внутри assigns, и если он есть, то текущий пользователь берётся в качестве параметра для метатега канала.  Теперь переходим к рефакторингу разметки верхней навигационной панели. Создайте файл web/templates/layout/navigation.html.eex: Это первый большой участок кода, в котором по полной используется Foundation. Здесь есть класс top-bar, а также различные вариации меню и сдвигов вправо/влево. Мы полностью вырезаем стандартные логотип Phoenix и навигационную панель и вместо этого используем простой текст в качестве логотипа. Ради простоты будем называть наш проект Phoenix Tech Blog. Также построим немного простого HTML с парой встроенных в Foundation стилей и компонентов. Ещё раз, в любом месте, где используется старый способ получения текущего пользователя, нужно заменить его на новый подход с использованием плага. В последнем примере используются описанные ниже классы: Теперь возьмёмся за блок оповещения, который также являются достаточно часто используемым кодом. Давайте создадим файл web/templates/layout/alerts.html.eex: Здесь нам нужно сделать чуть больше правок, так как у Phoenix по умолчанию есть конкретные ожидания относительно используемых классов CSS. Эти изменения сделают код блока предупреждений и стили чуть более платформонезависимыми. Если мы можем достать сообщение из conn, то соответственно отображаем его внутри div. Если нет, то не отображаем ничего. В исходном HTML-коде всё равно появится пустой div, но он никак не повлияет на отображение. У нас осталось 2 паршла, которые нужно доработать. Первый – основной контент. Обернём внутренности дива в классы row и content: Второй – шаблон для включение стандартного кода Javascript внизу. Создайте файл web/templates/layout/script.html.eex: Основная доработка здесь – это замыкание которое включается для вызова функции foundation() на объекте документа. Это требуется для встроенных в Foundation JS-хелперов. Наконец, давайте взглянем на макет приложения после нашего рефакторинга и на общий контент. Давайте изменим файл web/templates/layout/app.html.eex: Как вы можете заметить, макет приложения теперь выглядит куда более аккуратнее. Будет КРАЙНЕ удобно, если мы добавим новый макет для действия index из PageController, который назовём "splash page", что значит приветственная страница. Создайте файл нового макета `web/templates/layout/splash.html.eex: Здесь делается много всего, но по сути это просто контент с парой стилей здесь и там. Давайте взглянем ещё на несколько классов из Foundation: Наконец, сообщим Phoenix, что будем использовать новый макет для приветственного экрана в PageController. Откройте файл web/controllers/page_controller.ex и добавьте следующую строчку: Нам также нужно дать гостям возможность просмотреть последние N постов, так как было бы глупо делать прикольный блог, который никто не сможет читать. Для начала откройте файл web/router.ex и добавьте ресурс для постов с одним действием index. И затем откройте файл web/controllers/post_controller.ex, измените функцию index и добавьте ещё одну функцию index с использованием сопоставления с образцом. Но для начала измените плаг assign_user вверху файла: А теперь измените функцию index: Первый вызов проверяет наличие user_id в параметрах. Таким образом мы знаем, что получаем определённый пост для определённого пользователя. Если мы попали в эту функцию, то необходимо повторно использовать плаг assign_user для присвоения пользователя в conn. Чтобы не загружать пользователей для пустого массива, мы заранее проверяем наличие пользователя в assigns. Иначе просто возвращаем conn, который будет содержать переадресацию для несуществующего пользователя, флеш-сообщение и остановку запроса. Вторая функция index немного отличается. Нам нужно достать 5 самых свежих постов, так что ограничим их количество и предзагрузим пользователей в каждый пост. Не стоит волноваться по поводу комментариев, ведь их не нужно отображать на странице со списком постов. Здесь также нужно немного оптимизировать использование current_user. Для этого откройте файл web/templates/post/index.html.eex: Всё, что мы делали до – это там и сям прибирали стили. На всякий случай, код этих уроков находится здесь, так что можете посмотреть на все проделанные изменения, если хотите, чтобы у вас было всё один-в-один. Мы изменили часть разметки и функциональности, так что тесты упали. Чтобы их исправить, откройте файл test/controllers/page_controller_test.exs и измените проверку на “Phoenix Tech Blog”. Когда всё будет готово, вы должны увидеть подобную приветственную страницу:
 А вот что увидит гость, решив взглянуть на список постов:
 Теперь блог выглядит гораздо более профессионально. Плюс ко всему мы воспользовались Zurb Foundation 6 через Sass, а также jQuery и кучей других мелких бонусов. Ура! Проделана огромная работа, которая наконец-то подошла к концу. Теперь у всех интересующихся Эликсиром и Фениксом есть довольно неплохой вводный курс, который поможет познакомиться с технологиями.  Ещё несколько десятков статей по Эликсиру на русском языке вы можете найти на сайте нашего проекта. На вопросы отвечаем в Телеграм-чате, а о новых статьях и интересных событиях рассказываем в Телеграм-канале, а также в еженедельной ламповой рассылке. Подписывайтесь! Спасибо всем, кто прошёл данный обучающий курс до конца, кто сообщал об ошибках, а также автору оригинальных статей. Лучшей благодарностью от вас за то, что я нашёл силы и довёл работу до конца, будет плюс этой статье, пусть она не самая интересная в цикле, но выводя её в топ, мы поможем узнать об этом курсе куче новых людей, так что, пожалуйста, не пожалейте времени и рейтинга для этого. И до новых встреч!