Опубликован: 27.01.2016 | Уровень: для всех | Доступ: платный
Лекция 3:

В основном статические страницы

Embedded (встроенный) Ruby

Мы уже многого добились в этом разделе, создав три валидные страницы с использованием Rails контроллеров и действий, но они содержат совершенно статический HTML и, следовательно, не раскрывают возможностей Rails. Кроме того, они страдают от ужасного дублирования:

  • Заголовки страниц почти (но не совсем) одинаковые.
  • "Ruby on Rails Tutorial Sample App" является общим для всех трех заголовков (тайтлов).
  • Весь скелет структуры HTML повторяется на каждой странице.

Этот повторяющийся код - нарушение важного, "Don’t Repeat Yourself" (DRY, "Не Повторяй Себя") принципа; в этом и следующем разделах мы будем "DRY out" (# сушить) наш код, удаляя повторения.

Как это ни парадоксально, но первым шагом на пути устранения дублирования будет усиление дублирования: мы сделаем названия страниц, которые в настоящее время очень похожи, полностью совпадающими. Это позволит легко удалить все повторения одним махом.

Техника включает в себя использование Embedded Ruby в наших представлениях. Поскольку заголовки страниц Home, Help и About имеют переменную составляющую, мы будем использовать специальную Rails функцию называемую provide для установки отличающегося заголовка на каждой странице. Мы можем увидеть как это работает заменив буквальный заголовок "Home" в представлении home.html.erb кодом из Листинга 3.23.

<% provide(:title, 'Home') %>
<!DOCTYPE html>
<html>
  <head>
    <title>Ruby on Rails Tutorial Sample App | <%= yield(:title) %></title>
  </head>
  <body>
    <h1>Sample App</h1>
    <p>
      This is the home page for the
      <a href="http://railstutorial.org/">Ruby on Rails Tutorial</a>
      sample application.
    </p>
  </body>
</html>
Листинг 3.23. Представление для страницы Home с Embedded (встроенным) Ruby заголовком. app/views/static_pages/home.html.erb

Листинг 3.23 это наш первый пример Embedded Ruby, также называемого ERb. (Теперь вы знаете, почему HTML представления имеют расширение .html.erb.) ERb это основная система шаблонов для включения динамического контента в веб-страницы.9Существует еще одна популярная система темплейтов которая называется Haml, которую лично мне очень нравится, но она пока не настолько популярна чтобы использовать ее во вводном учебнике. Код

<% provide(:title, 'Home') %>

указывает с помощью <% ... %> что Rails должны вызвать функцию provide и связать строку ’Home’ с заголовком :title.10Опытные Rails программисты возможно ожидали увидеть здесь content_for, но он плохо работает с файлопроводом. Функция provide это его замена Затем, в заголовке, мы используем тесно связанную нотацию <%= ... %> для вставки заголовка в шаблон используя Ruby-функцию yield:11Если вы изучали Ruby прежде, вы могли бы подозревать, что Rails передает содержимое в блок, и ваша догадка была бы правильной. Но для разработки веб-приложений с Rails это не имеет значения.

<title>Ruby on Rails Tutorial Sample App | <%= yield(:title) %></title>

(Разница между этими двумя типами встроенного Ruby заключается в том, что <% ... %> исполняет код внутри, в то время как <%= ... %> исполняет и вставляет его в шаблон.) Получившаяся в результате страница совершенно не изменилась, вот только изменяющаяся часть заголовка динамически сгенерирована встроенным Руби

Мы можем проверить что все это работает запустив тесты из Раздела 3.3.1 и увидев что они все еще проходят:

$ bundle exec rspec spec/requests/static_pages_spec.rb

Затем мы можем сделать соответствующие замены для Help и About страниц (Листинг 3.24 и Листинг 3.25).

<% provide(:title, 'Help') %>
<!DOCTYPE html>
<html>
  <head>
    <title>Ruby on Rails Tutorial Sample App | <%= yield(:title) %></title>
  </head>
  <body>
    <h1>Help</h1>
    <p>
      Get help on the Ruby on Rails Tutorial at the
      <a href="http://railstutorial.org/help">Rails Tutorial help page</a>.
      To get help on this sample app, see the
      <a href="http://railstutorial.org/book">Rails Tutorial book</a>.
    </p>
  </body>
</html>
Листинг 3.24. Представление для страницы Help с Embedded Ruby заголовком. app/views/static_pages/help.html.erb
<% provide(:title, 'About Us') %>
<!DOCTYPE html>
<html>
  <head>
    <title>Ruby on Rails Tutorial Sample App | <%= yield(:title) %></title>
  </head>
  <body>
    <h1>About Us</h1>
    <p>
      The <a href="http://railstutorial.org/">Ruby on Rails Tutorial</a>
      is a project to make a book and screencasts to teach web development
      with <a href="http://rubyonrails.org/">Ruby on Rails</a>. This
      is the sample application for the tutorial.
    </p>
  </body>
</html>
Листинг 3.25. Представление для страницы About с Embedded Ruby заголовком. app/views/static_pages/about.html.erb

Устранение дублирования шаблонами

Теперь, когда мы заменили переменную часть заголовков страниц на ERb, каждая из наших страниц выглядит примерно так:

<% provide(:title, 'Foo') %>
<!DOCTYPE html>
<html>
  <head>
    <title>Ruby on Rails Tutorial Sample App | <%= yield(:title) %></title>
  </head>
  <body>
      Contents
  </body>
</html>

Другими словами, все наши страницы имеют одинаковую структуру, в том числе, заголовки (из-за Embedded Ruby), исключая содержимое body тега.

Для того чтобы факторизировать ("вынести за скобки") эту повторяющуюся структуру, Rails предоставляет специальный layout файл называемый application.html.erb, который мы переименовали в Разделе 3.3.1 и который мы теперь восстановим:

$ mv foobar app/views/layouts/application.html.erb

Для того чтобы получить работающий макет, мы должны заменить дефолтный заголовок на Embedded Ruby из примеров выше:

<title>Ruby on Rails Tutorial Sample App | <%= yield(:title) %></title>

Получившийся макет представлен в Листинге 3.25.

<!DOCTYPE html>
<html>
<head>
  <title>Ruby on Rails Tutorial Sample App | <%= yield(:title) %></title>
  <%= stylesheet_link_tag    "application", media: "all",
                                            "data-turbolinks-track" => true %>
  <%= javascript_include_tag "application", "data-turbolinks-track" => true %>
  <%= csrf_meta_tags %>
</head>
<body>

<%= yield %>

</body>
</html>
Листинг 3.26. Листинг 3.26. Макет сайта примера приложения. app/views/layouts/application.html.erb

Обратите здесь внимание на специальную строку

<%= yield %>

Этот код отвечает за вставку содержимого каждой страницы в макет. Нет необходимости понимать как это на самом деле работает; куда важнее то, что использование этого макета обеспечивает, например, преобразование содержимого home.html.erb в HTML и последующую его вставку на место <%= yield %>.

Также стоит отметить что дефолтный Rails-макет включает несколько дополнительных строк:

<%= stylesheet_link_tag ... %>
<%= javascript_include_tag "application", ... %>
<%= csrf_meta_tags %>

Этот код организует подключение стилей и JavaScript приложения, являющихся частью файлопровода (Раздел 5.2.1), совместно с Rails методом csrf_meta_tags, который предотвращает подделку межсайтовых запросов (CSRF), вид злонамеренной веб-атаки.

Конечно, представления в Листинге 3.23, Листинге 3.24, и Листинге 3.25 по-прежнему заполнены полной HTML структурой включенной в макет, так что мы должны удалить ее, оставив только внутреннее содержимое. Получившиеся после очистки представления представлены в Листинге 3.27, Листинге 3.28, и Листингt 3.29.

<% provide(:title, 'Home') %>
<h1>Sample App</h1>
<p>
  This is the home page for the
  <a href="http://railstutorial.org/">Ruby on Rails Tutorial</a>
  sample application.
</p>
Листинг 3.27. Home страница с удаленной HTML структурой. app/views/static_pages/home.html.erb
<% provide(:title, 'Help') %>
<h1>Help</h1>
<p>
  Get help on the Ruby on Rails Tutorial at the
  <a href="http://railstutorial.org/help">Rails Tutorial help page</a>.
  To get help on this sample app, see the
  <a href="http://railstutorial.org/book">Rails Tutorial book</a>.
</p>
Листинг 3.28. Страница Help с удаленной HTML структурой. app/views/static_pages/help.html.erb
<% provide(:title, 'About Us') %>
<h1>About Us</h1>
<p>
  The <a href="http://railstutorial.org/">Ruby on Rails Tutorial</a>
  is a project to make a book and screencasts to teach web development
  with <a href="http://rubyonrails.org/">Ruby on Rails</a>. This
  is the sample application for the tutorial.
</p>
Листинг 3.29. Страница About с удаленной HTML структурой. app/views/static_pages/about.html.erb

С таким определением представлений, Home, Help, и About страницы точно такие же, как и прежде, но дублирования стало гораздо меньше. Проверка того что набор тестов по-прежнему проходит даст нам уверенность в том что этот рефакторинг кода прошел успешно:

$ bundle exec rspec spec/requests/static_pages_spec.rb
Вадим Обозин
Вадим Обозин

Здравствуйте, записался на курс. При этом ставил галочку на "обучаться с тьютором". На email пришло письмо, о том, что записался на самостоятельное изучение курса. Как выбрать тьютора?

Акбар Ахвердов
Акбар Ахвердов
Россия, г. Москва
Артём Зайцев
Артём Зайцев
Украина, ДНР