Мультиблог на Ruby on Rails. Работа с шаблоном. Подключение CSS и JS. Урок 5.
При написании данного урока мною было принято решение не верстать с нуля, а взять за основу готовый бесплатный шаблон «Clean blog». Сделано так потому, что у нас урок всё-таки больше по созданию блога, а не по вёрстке. Тем более, на сайте уже есть уроки по HTML, где я постарался раскрыть данную тему максимально доходчиво.
Создание базового шаблона
Грубо говоря, под базовым шаблоном понимаются те части HTML каркаса страницы, которые не меняются - у большинства сайтов это шапка, подвал, левое меню и прочие элементы навигации. Базовый шаблон в Ruby on Rails находится по пути app/views/layouts/application.html.erb; удалим всё, что в нём есть и разместим там содержимое файла index.html из нашего готового шаблона. Теперь если обновить главную страничку, то можно увидеть что она поменялась, но выглядит как-то не круто - это всё потому, что у нас не подключены стили CSS.
Подключение стилей
В "рельсах" за стили отвечает файл app/assets/stylesheets/application.css В нём, помимо комментариев, есть две конструкции:
- *= require_tree . - рекурсивно подключает все CSS файлы, которые находятся в папке app/assets/stylesheets/
- *= require_self - отвечает за стили, которые находятся уже в самом файле application.css
Но чтобы это всё работало, надо подключить CSS файл в базовый шаблон:
<%= stylesheet_link_tag "application", "data-turbo-track": "reload" %>
Смотрим какие CSS файлы у нас есть в шаблоне. Возьмём к примеру файл vendor/bootstrap/css/bootstrap.min.css Как я его подключил? Я создал внутри папки app/assets/stylesheets/ папку bootstrap и в неё скопировал файл bootstrap.min.css из самого шаблона. Теперь если обновить страничку, то можно увидеть что стили подключены. Аналогичные действия я проделал и для других CSS файлов:
vendor/fontawesome-free/css/all.min.css
css/clean-blog.min.css
Однако, если мы сейчас обновим страничку, то обнаружим что не все иконки подгрузились. Связано это с тем, что в css файле путь к шрифту смотрит на папку webfonts, которая лежит на уровень выше - в нашем случае это папка public. Значит всё, что нужно сделать, это скопировать папку /vendor/fontawesome-free/webfonts в папку /public нашего проекта. И если сейчас обновить страничку, то мы увидим что все шрифты подгрузились.
Подключение Javascript файлов
Первым делом, выносим все JS файлы в папку app/javascript В нашем случае это файлы jquery.min.js, bootstrap.bundle.min.js и clean-blog.min.js Соответственно ссылки на эти файлы из самого шаблона мы удаляем, а вместо этого размещаем их следующим образом:
<%= javascript_include_tag 'jquery.min.js' %> <%= javascript_include_tag 'bootstrap.bundle.min.js' %> <%= javascript_include_tag 'clean-blog.min.js' %>
Обновление страниц без перезагрузки. Turbolinks.
У Ruby on Rails есть такая удобная фишка, как обновление контентной части без перезагрузки самой страницы. Чтобы это заработало, необходимо в базовый шаблон разместить тэг:
<%= javascript_importmap_tags %>
Не сказать что это нам прямо-таки необходимо, но раз это стоит минимальных усилий, то почему бы не воспользоваться теми удобствами, которые предлагает фреймворк.
Понятие дочерней страницы
Дочерняя страница - это view шаблон, который путём наследования подключает базовый (родительский) шаблон и изменяет данные в специально отведённых для этого секциях. Если попытаться перевести всё это на более понятный язык, то давайте ответим себе на вопрос: "что у нас обычно меняется при переходе по страничкам сайта?". Правильно, это контентная часть. Но чтобы она менялась, надо как-то обозначить секцию для контента в базовом шаблоне. За это отвечает следующая конструкция:
<%= yield %>
Если же говорить о дочерней странице, то таковой у нас является страничка index.html.erb Опять же, почему именно она? Потому что мы находимся на главной странице, которая привязана к action index контролера posts; а сам контролер, в соответствии со своим расположением, обращается к файлу views/posts/index.html.erb Теперь вопрос в том, а где эту конструкцию yield разместить? Конечно же в контентной части, ровно там, где у нас выводятся посты на главной странице.
Размещение нескольких секций yield
Всё это время мы говорили о секции для контента, однако у нас таких секций может быть несколько. Одна для изменения заголовка H1, вторая для изменения тэга title, третья для размещения картинки. Тут возникает вопрос, как обозначить их все в базовом шаблоне? Разберём на примере заголовка H1, секцию для которого обозначим так:
<h1><%= yield(:h1) %></h1>
А в дочернем шаблоне переопределим это место в index.html.erb следующим образом:
<% content_for :h1 do %> Список записей <% end %>
Аналогичное действие проделываем и для тэга title:
<title><%= yield(:title) %></title>
В дочернем шаблоне соответственно секцию подгружаем так:
<% content_for :title do %> Список записей <% end %>
Стилизация отдельного поста внутри цикла или понятие частичного (partial) шаблона
Теперь у нас главная страничка выглядит более красиво, однако этого нельзя сказать об отображении самих постов - там по-прежнему неструктурированная каша. Именно для этих целей RoR предоставляет рендеринг шаблонов внутри шаблонов (иногда их называют ещё partial шаблоны, так как они не предполагают наследования). Используется это в основном там, где необходимо оформить элементы, вывод которых происходит в цикле. Я разместил такой файл по пути app/views/posts/_post.html.erb (partial шаблон принято именовать с символа _) со следующим содержимым:
<div class="post-preview"> <a href="#"> <h2 class="post-title"> <%= post.title %> </h2> <h3 class="post-subtitle"> <%= post.body.truncate(255, '…') %> </h3> </a> <p class="post-meta">Posted by <a href="#">Start Bootstrap</a> on <%= post.created_at.strftime('%d-%m-%Y %H:%M') %> </p> </div> <hr>
Тут наверное стоит рассказать о вспомогательных методах:
truncate - отвечает за обрезку контента до определённого количества символов. Первый аргумент - это количество таких символов, второй - строка, которая будет идти в конце текста (в данном случае троеточие).
strftime - форматирование даты. Хочу обратить внимание, что поле created_at у нас всегда создаётся по умолчанию при создании миграции и заполняется автоматом.
А в самом шаблоне index.html.erb мы будем подгружать этот partial шаблон так:
<% @posts.each do |post| %> <%= render 'post', post: post %> <% end %>
То есть здесь мы в цикле итерируем переменную posts, и на каждом шаге передаём статью (локальная переменная post) в шаблон _post.html.erb
Добавление статичных картинок
На главной странице у нас должна отображаться картинка about-bg.jpg, которую я разместил в папке /public/images/ Но прежде чем её вывести, сперва необходимо обозначить соответствующую секцию в базовом шаблоне:
<%= yield(:image) %>
Теперь перезаписываем секцию родительского шаблона:
<% content_for :image do %><%= '/images/about-bg.jpg' %><% end %>
Обновляем страничку и убеждаемся что картинка на месте.
Итог работы
Итак, в этом уроке мы создали базовый шаблон и научились переопределять его секции из дочернего шаблона. В следующих уроках займёмся добавлением нового функционала и подключением остальных страниц. Что касается главной страницы, то в качестве последнего штриха, можно проставить ссылку на неё - для этого достаточно в базовом шаблоне везде поменять адрес страницы с index.html на /
Урок получился достаточно объёмным, поэтому чтобы вы ничего не упустили, вот коммит со всеми текущими изменениями в помощь.