Глава 5 Заполнение шаблона
В процессе краткого обзора Ruby в Главе 4, мы добавили базовые таблицы каскадных стилей в шаблон нашего сайта (Раздел 4.1.2). В этой главе мы добавим собственную таблицу стилей, добавим в шаблон ссылки на страницы (например, Home и About), которые мы создали ранее. В процессе мы узнаем о частичных шаблонах (partials), Rails маршрутах, а также об интеграционных тестах. Мы закончим, сделав первый важный шаг на пути создания опции регистрации пользователей на нашем сайте.5.1 Добавление некоторых структур
Rails Учебник это книга по веб-разработке, а не по веб-дизайну, но работа над приложением, которое выглядит как полное дерьмо - удручает, поэтому, в этом разделе мы добавим некоторые структуры в шаблон и придадим ему минимальный дизайн с CSS. Мы также придадим нашему коду немного стиля, так сказать, используя частичные шаблоны почистим шаблон, поскольку он немного загроможден.При создании веб-приложений, часто бывает полезным получить общий вид пользовательского интерфейса как можно раньше. Таким образом, на протяжении остальной части книги, я буду часто использовать макеты (в контексте Веб часто называемыми каркасами), которые являются грубыми набросками того, как приложение, возможно, будет выглядеть.1 В этой главе мы будем главным образом разрабатывать статические страницы введеные в Разделе 3.1, включая логотип сайта, заголовок с навигацией по сайту, и подвал сайта. Каркас для наиболее важной из страниц — Home страницы, представлен на Рис. 5.1. (Вы можете увидеть конечный результат на Рис. 5.8. Он отличается в некоторых деталях, например, подвал имеет четыре ссылки вместо трех, но это нормально, так как каркас и не должен быть абсолютно точным.)
Рис. 5.1: Каркас Home страницы примера приложения. (полный размер)
$ git checkout -b filling-in-layout
example_user.rb файл из Главы 4 в каталоге вашего проекта, если это так, то вам следует просто удалить его.5.1.1 Навигация по сайту
Когда мы последний раз видели файл шаблона сайтаapplication.html.erb в Листинге 4.3, мы только что добавили к нему таблицы стилей Blueprint, используя Rails помощник stylesheet_link_tag.
Пришло время добавить еще пару таблиц стилей, одну специально для
интернет-браузеров Explorer и одну для нашего (скоро-будет-добавлен)
пользовательского CSS. Мы также добавим несколько дополнительных (div-ов), несколько id и class-ов, и запустим навигацию по нашему сайту. Законченный файл — в Листинге 5.1;
объяснения различных частей последуют сразу за ним. Если вы не хотите
откладывать удовольствие, вы можете посмотреть на результаты
представленные на Рис. 5.2. (Примечание: это (пока) не очень приятно.)
Листинг 5.1. Шаблон сайта с добавленными структурами.
app/views/layouts/application.html.erb
<!DOCTYPE html>
<html>
<head>
<title><%= title %></title>
<%= csrf_meta_tag %>
<!--[if lt IE 9]>
<script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<%= stylesheet_link_tag 'blueprint/screen', :media => 'screen' %>
<%= stylesheet_link_tag 'blueprint/print', :media => 'print' %>
<!--[if lt IE 8]><%= stylesheet_link_tag 'blueprint/ie' %><![endif]-->
<%= stylesheet_link_tag 'custom', :media => 'screen' %>
</head>
<body>
<div class="container">
<header>
<%= image_tag("logo.png", :alt => "Sample App", :class => "round") %>
<nav class="round">
<ul>
<li><%= link_to "Home", '#' %></li>
<li><%= link_to "Help", '#' %></li>
<li><%= link_to "Sign in", '#' %></li>
</ul>
</nav>
</header>
<section class="round">
<%= yield %>
</section>
</div>
</body>
</html>
<!DOCTYPE html>);
т.к. HTML5 — новый стандарт, и некоторые браузеры (особенно Internet
Explorer) пока не полностью его поддерживают, так что мы включим
JavaScript код (известный как “HTML5 shiv”) чтобы обойти это затруднение:<!--[if lt IE 9]>
<script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<!--[if lt IE 9]>
if lt IE 9). Чудной [if lt IE 9] синтаксис не является частью Rails; это условный комментарий
поддерживаемый браузерами Internet Explorer специально для подобных
ситуаций. Это хорошая вещь, хотя бы потому, что это означает, что мы
можем включить дополнительную таблицу стилей только для IE браузеров версии менее 9, не затрагивая такие браузеры как Firefox и Safari.После строки, включающей стили Blueprint (впервые представлена в Листинге 4.4), идет другая Internet Explorer–специфичная строка, в этот раз это стиль, который включается только если версия Internet Explorer ниже чем 8 (
if lt IE 8):<!--[if lt IE 8]><%= stylesheet_link_tag 'blueprint/ie' %><![endif]-->
ie.css файл, исправляющий значительную часть из них.За IE стилем идет ссылка на файл, который еще не существует,
custom.css, в котором мы разместим наши пользовательские CSS:<%= stylesheet_link_tag 'custom', :media => 'screen' %>
custom.css в Разделе 5.1.2.)В следующем разделе расположился контейнер div окружающий навигацию по сайту и контент, контейнер определяется
div тегом с классом container. Этот контейнер DIV необходим Blueprint-у (см. подробности в Blueprint tutorial Далее идут header и section элементы; header содержит логотип "sample app" (будет добавлен позже) и навигацию по сайту (nav). И последний элемент - section, содержащий основной контент сайта:<div class="container">
<header>
<%= image_tag("logo.png", :alt => "Sample App", :class => "round") %>
<nav class="round">
<ul>
<li><%= link_to "Home", '#' %></li>
<li><%= link_to "Help", '#' %></li>
<li><%= link_to "Sign in", '#' %></li>
</ul>
</nav>
</header>
<section class="round">
<%= yield %>
</section>
</div>
div тег в HTML это generic division (# "родовое отделение" — если верить автопереводчику :) ); он не делает ничего, кроме разделения документа на отдельные части. В старом стиле HTML, div теги использовали почти для всех разделов сайта, но HTML5 добавил header, nav, и section
элементы для разделов, общих для многих приложений. Всем элементам
HTML, включая дивы и новые HTML5 элементы, могут быть присвоены классы2 и id (идентификаторы); это всего лишь ярлыки, и они полезны для создания стиля с CSS (Раздел 5.1.2).
Основное различие между классами и идентификаторами, в том, что классы
могут быть использованы несколько раз на странице, а идентификаторы
могут быть использованы лишь один раз.Внутри header находится Rails помощник, называемый
image_tag:<%= image_tag("logo.png", :alt => "Sample App", :class => "round") %>
stylesheet_link_tag (Раздел 4.3.4), мы передаем хэш опций, в данном случае для назначения alt и class атрибутов image тега, используются символы :alt и :class. Чтобы прояснить это, давайте посмотрим на HTML который этот тег производит:3<img alt="Sample App" class="round" src="/images/logo.png" />
alt атрибут, это то, что будет отображаться, если нет изображения,4 и class будет использоваться для создания стиля в Разделе 5.1.2.
(Rails хелперы часто принимают хэши опций именно таким образом, что
позволяет нам гибко добавлять произвольные варианты HTML, не покидая
Rails.) Вы можете увидеть результаты на Рис. 5.2; логотип мы добавим в конце этого раздела.Второй элемент внутри header это список навигационных ссылок, сделанный с использованием тега ненумерованного списка —
ul, и тега элемента списка li:<nav class="round">
<ul>
<li><%= link_to "Home", '#' %></li>
<li><%= link_to "Help", '#' %></li>
<li><%= link_to "Sign in", '#' %></li>
</ul>
</nav>
link_to для создания ссылок (которые мы создавали непосредственно с якорным (анкорным) тегом a в Разделе 3.3.2); первый аргумент это текст ссылки, а второй это URL. Мы заполним URL-адреса именованными маршрутами в Разделе 5.2.3, но сейчас мы используем заглушки URL ’#’
обычно применяемые в веб-дизайне. После Rails обработки этого шаблона и
оценки Embedded Ruby, список выглядит следующим образом:<nav class="round">
<ul>
<li><a href="#">Home</a></li>
<li><a href="#">Help</a></li>
<li><a href="#">Sign in</a></li>
</ul>
</nav>
home.html.erb представление (Листинг 5.2).
Листинг 5.2. Home страница со ссылкой на страницу регистрации.
app/views/pages/home.html.erb
<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>
<%= link_to "Sign up now!", '#', :class => "signup_button round" %>
link_to, это только создает ссылку-заглушку вида<a href="#" class="signup_button round">Sign up now!</a>
a тег здесь имеет два класса, разделенные пробелом: <a href="#" class="signup_button round">
Теперь мы, наконец, готовы увидеть плоды наших трудов (Рис. 5.2).5 Говорите "Не впечатляет"? Может быть. К счастью, однако, мы проделали хорошую работу, прописав для наших HTML элементов внятные классы и идентификаторы, которые позволят нам добавить стиль на сайт с помощью CSS.
Рисунок 5.2: Home страница (/pages/home) без логотипа и пользовательского CSS. (полный размер)
http://railstutorial.org/images/sample_app/logo.png
Поместите логотип в
public/images чтобы Rails смог его найти. Результат — в Рис. 5.3.
Рисунок 5.3: Home страница (/pages/home) с логотипом, но без пользовательского CSS. (полный размер)
5.1.2 Пользовательские CSS
В Разделе 5.1.1, вы могли заметить, что элементы CSS семантичны, то есть, обозначающие их слова, имеют значение в английском языке за пределами структуры страницы. Например, вместо того чтобы писать, что навигационное меню было “right-top” мы использовали “nav”. Это дает нам значительную гибкость при построении шаблона на основе CSS.Давайте начнем с заполнения файла
custom.css кодом из Листинга 5.3. (В Листинге 5.3.
содержится немало правил. Чтобы получить представление о том, что
именно делает каждое конкретное правило CSS, часто бывает полезным,
закомментировать его с помощью CSS комментария, т. е., поместить его в /* … */, и посмотреть, что изменилось.
Листинг 5.3. CSS для container, body, и ссылок.
public/stylesheets/custom.css
.container {
width: 710px;
}
body {
background: #cff;
}
header {
padding-top: 20px;
}
header img {
padding: 1em;
background: #fff;
}
section {
margin-top: 1em;
font-size: 120%;
padding: 20px;
background: #fff;
}
section h1 {
font-size: 200%;
}
/* Links */
a {
color: #09c;
text-decoration: none;
}
a:hover {
color: #069;
text-decoration: underline;
}
a:visited {
color: #069;
}
body {
background: #cff;
}
body тега на голубой, аheader img {
padding: 1em;
background: #fff;
}
em (ширина строчной (маленькой) буквы m) вокруг изображения (img) внутри header тега. Это правило также делает цвет фона белым (#fff).6 Аналогичным образом,.container {
width: 710px;
}
container, в данном случае, придавая ему ширину в 710 пикселов (что соответствует 18 столбцам Blueprint).7 Точка . в .container обозначает что это правило для класса называемого “container”. (как мы увидим в Разделе 8.2.3, знак фунт # указывает (также как и точка в случае CSS класса), что это правило для id.)
Рисунок 5.4: Home страница (/pages/home) с пользовательскими цветами. (полный размер)
Листинг 5.4. CSS для навигации по сайту.
public/stylesheets/custom.css
.
.
.
/* Navigation */
nav {
float: right;
}
nav {
background-color: white;
padding: 0 0.7em;
white-space: nowrap;
}
nav ul {
margin: 0;
padding: 0;
}
nav ul li {
list-style-type: none;
display: inline-block;
padding: 0.2em 0;
}
nav ul li a {
padding: 0 5px;
font-weight: bold;
}
nav ul li a:visited {
color: #09c;
}
nav ul li a:hover {
text-decoration: underline;
}
nav ul стилизует ul тег внутри nav тега, nav ul li стилизует li тег внутри ul тега внутри nav тега, и так далее.
Рисунок 5.5: Home страница (/pages/home) с отстиленной навигацией по сайту. (полный размер)
Листинг 5.5. CSS делающий регистрационную кнопку большой, зеленой и кликабельной.
public/stylesheets/custom.css
.
.
.
/* Sign up button */
a.signup_button {
margin-left: auto;
margin-right: auto;
display: block;
text-align: center;
width: 190px;
color: #fff;
background: #006400;
font-size: 150%;
font-weight: bold;
padding: 20px;
}
Рисунок 5.6: Home страница (/pages/home) с signup кнопкой. (полный размер)
round
класс, который мы присвоили многим элементам нашего сайта. Хотя в
нынешних острых углах блоков нет ничего страшного, смягчение углов
придаст интерфейсу бОльшую дружелюбность. Мы можем сделать это,
используя CSS код из Листинга 5.6, результаты показаны на Рис. 5.7.
Листинг 5.6. Правила таблицы стилей для скругления углов.
public/stylesheets/custom.css
.
.
.
/* Round corners */
.round {
-moz-border-radius: 10px;
-webkit-border-radius: 10px;
border-radius: 10px;
}
Рисунок 5.7: Home страница (/pages/home) со скругленными углами. (полный размер)
5.1.3 Частичные шаблоны (partials)
Хотя шаблон в Листинге 5.1 все еще служит своей цели, он становится немного суматошным: есть четыре строки, включающие CSS и восемь строк header-а, что логически, несет в себе всего две идеи (включить CSS и причесать header). Мы можем убрать эти разделы, используя удобный объект Rails называемый partials (частичные шаблоны, партиалы). Давайте сначала посмотрим, как шаблон выглядит после определения партиалов (Листинг 5.7).
Листинг 5.7. Шаблон сайта с партиалами для ссылок на таблицы стилей и header-а.
app/views/layouts/application.html.erb
<!DOCTYPE html>
<html>
<head>
<title><%= title %></title>
<%= csrf_meta_tag %>
<%= render 'layouts/stylesheets' %>
</head>
<body>
<div class="container">
<%= render 'layouts/header' %>
<section class="round">
<%= yield %>
</section>
</div>
</body>
</html>
render:<%= render 'layouts/stylesheets' %>
app/views/layouts/_stylesheets.html.erb, оценка его содержания, и вставка результата оценки в представление.8 (Напомним, что <%= ... %>
это Embedded Ruby синтаксис, необходимый для оценки выражения Ruby и
последующей вставки результата в шаблон. Обратите внимание на символ
подчеркивания в имени файла _stylesheets.html.erb; это
подчеркивание - универсальное соглашение для именования частичных
шаблонов, которое, среди прочего, позволяет идентифицировать все
партиалы в каталоге с первого взгляда.Конечно, чтобы заполучить частичные шаблоны на работу, мы должны заполнить их некоторым содержанием; в случае частичного шаблона для таблиц стилей, это всего лишь четыре ссылки на таблицы стилей, взятые из Листинга 5.1; результат представлен в Листинге 5.8. (Технически, HTML5 shiv включает JavaScript, а не CSS. C другой стороны, его назначение - дать возможность Internet Explorer-у понимать CSS с HTML5, так что, логически, он по-прежнему принадлежит к _stylesheets партиалу.)
Листинг 5.8. Частичный шаблон включающий таблицы стилей.
app/views/layouts/_stylesheets.html.erb
<!--[if lt IE 9]>
<script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<%= stylesheet_link_tag 'blueprint/screen', :media => 'screen' %>
<%= stylesheet_link_tag 'blueprint/print', :media => 'print' %>
<!--[if lt IE 8]><%= stylesheet_link_tag 'blueprint/ie' %><![endif]-->
<%= stylesheet_link_tag 'custom', :media => 'screen' %>
render:<%= render 'layouts/header' %>
Листинг 5.9. Партиал для header-а сайта.
app/views/layouts/_header.html.erb
<header>
<%= image_tag("logo.png", :alt => "Sample App", :class => "round") %>
<nav class="round">
<ul>
<li><%= link_to "Home", '#' %></li>
<li><%= link_to "Help", '#' %></li>
<li><%= link_to "Sign in", '#' %></li>
</ul>
</nav>
</header>
_footer.html.erb и поместим его в layouts каталог (Листинг 5.10).
Листинг 5.10. Частичный шаблон для подвала сайта.
app/views/layouts/_footer.html.erb
<footer>
<nav class="round">
<ul>
<li><%= link_to "About", '#' %></li>
<li><%= link_to "Contact", '#' %></li>
<li><a href="http://news.railstutorial.org/">News</a></li>
<li><a href="http://www.railstutorial.org/">Rails Tutorial</a></li>
</ul>
</nav>
</footer>
link_to для внутренних ссылок на About и Contact страницы и заглушили URL-адреса символом ’#’ до лучших времен. (Как и header, footer - новый, HTML5, тег.)Мы можем вставить партиал подвала в шаблон тем же образом, что и stylesheets и header партиалы (Листинг 5.11).
Листинг 5.11. Шаблон сайта с партиалом подвала.
app/views/layouts/application.html.erb
<!DOCTYPE html>
<html>
<head>
<title><%= title %></title>
<%= csrf_meta_tag %>
<%= render 'layouts/stylesheets' %>
</head>
<body>
<div class="container">
<%= render 'layouts/header' %>
<section class="round">
<%= yield %>
</section>
<%= render 'layouts/footer' %>
</div>
</body>
</html>
Листинг 5.12. Добавлениеe CSS для частичного шаблона подвала.
public/stylesheets/custom.css
.
.
.
footer {
text-align: center;
margin-top: 10px;
width: 710px;
margin-left: auto;
margin-right: auto;
}
footer nav {
float: none;
}
footer nav {
float: none;
}
nav {
float: right;
}
Рисунок 5.8: Home страница (/pages/home) с добавленным подвалом. (полный размер)
5.2 Ссылки в шаблоне
Теперь, когда мы закончили шаблон сайта с достойным стилем, пришло время приступить к заполнению ссылок которые мы заглушили символом’#’. Конечно, мы могли бы жестко захардкодить ссылки:<a href="/pages/about">About</a>
<%= link_to "About", about_path %>
about_path и URL изменятся везде где используется about_path.Полный список наших запланированных ссылок представлен в Таблице 5.1, вместе с соответствием URI и маршрутов. Со временем, мы реализуем все ссылки, но предпоследнюю мы добавим только в конце этой главы, а последняя будет создана лишь в Главе 9.
| Страница | URL | Именованный маршрут |
|---|---|---|
| Home | / | root_path |
| About | /about | about_path |
| Contact | /contact | contact_path |
| Help | /help | help_path |
| Sign up | /signup | signup_path |
| Sign in | /signin | signin_path |
Таблица 5.1: Маршруты и соответствующие URL для ссылок сайта.
5.2.1 Интеграционные тесты
Перед написанием маршрутов для нашего приложения, мы продолжим с нашим TDD, написав несколько тестов для них. Есть несколько способов проверить маршруты, и я собираюсь воспользоваться этой возможностью, чтобы представить интеграционные (объединенные) тесты, которые дают нам возможность симулировать доступ браузера к нашему приложению и таким образом протестировать его от начала и до конца. Как мы увидим в Разделе 8.4, тестирование маршрутов это только начало.Мы начнем с генерации интеграционного теста для ссылок в шаблоне примера приложения:
$ rails generate integration_test layout_links
invoke rspec
create spec/requests/layout_links_spec.rb
_spec.rb к имени нашего тестового файла, сохраняя его как spec/requests/layout_links_spec.rb. (В RSpec, интеграционные тесты также называют request specs (спецификация запросов); происхождение этой терминологии мне неясно.)Наши интеграционные тесты будут использовать ту же
get функцию, что мы использовали в Разделе 3.2 в Pages контроллер spec, с кодом вроде этого:describe "GET 'home'" do
it "should be successful" do
get 'home'
response.should be_success
end
end
get
эти URL-адреса внутри контроллера теста — контроллер тестов знает
только об URL-адресах, определенных для этого конкретного контроллера. В
отличие от интеграционных (объединенных) тестов, не связанных такими
ограничениями, так как они выполнены в виде интегрированных (комплексных, объединенных) тестов для всего приложения и, следовательно, могут get любую страницу, какую захотят.Следуя модели Pages контроллера spec, мы можем написать интеграционную спецификацию (spec) для каждой из страниц, указанных в Таблице 5.1 (за исключением тех, которые мы еще не создали); а именно, Home, About, Contact, и Help. Чтобы убедиться в правильности воспроизводимой в каждом случае страницы (т.е. представления), мы проверим правильность заголовка используя
have_selector. Тесты представлены в Листинге 5.13.
Листинг 5.13. Интеграционные тесты для маршрутов.
spec/requests/layout_links_spec.rb
require 'spec_helper'
describe "LayoutLinks" do
it "should have a Home page at '/'" do
get '/'
response.should have_selector('title', :content => "Home")
end
it "should have a Contact page at '/contact'" do
get '/contact'
response.should have_selector('title', :content => "Contact")
end
it "should have an About page at '/about'" do
get '/about'
response.should have_selector('title', :content => "About")
end
it "should have a Help page at '/help'" do
get '/help'
response.should have_selector('title', :content => "Help")
end
end
Кстати, если у вас нет Help страницы в этой точке, то сейчас хорошее время, чтобы добавить ее. (Если вы решили упражнения Главы 3 в Разделе 3.5, она у вас уже есть.) Во-первых, добавьте
help действие в контроллер Pages (Листинг 5.14). Затем создайте соответствующее представление (Листинг 5.15).
Листинг 5.14. Добавление
help действия в контроллер Pages. app/controllers/pages_controller.rb
class PagesController < ApplicationController
.
.
.
def help
@title = "Help"
end
end
Листинг 5.15. Добавление представления для Help страницы.
app/views/pages/help.html.erb
<h1>Help</h1>
<p>
Get help on 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>
spec/requests каталоге (Листинг 5.16 или Листинг 5.17).
Листинг 5.16. Дополнения к
.autotest, необходимые для запуска интеграционного (объединенного) теста с Autotest на OS X.
Autotest.add_hook :initialize do |autotest|
autotest.add_mapping(/^spec\/requests\/.*_spec\.rb$/) do
autotest.files_matching(/^spec\/requests\/.*_spec\.rb$/)
end
end
Листинг 5.17. Дополнения к
.autotest, необходимые для запуска интеграционного теста с Autotest на Ubuntu Linux.
Autotest.add_hook :initialize do |autotest|
autotest.add_mapping(%r%^spec/(requests)/.*rb$%) do|filename, _|
filename
end
end
.autotest файл, он работал.)5.2.2 Rails маршруты
Теперь, когда у нас есть тесты для URL, такие как мы хотим, пришло время заставить их работать. Как отмечалось в Разделе 3.1.2, Rails использует для маршрутов файлconfig/routes.rb.
Если вы посмотрите на дефолтный (по умолчанию) файл routes.rb, вы
увидите беспорядок, но это полезный беспорядок — полный
закомментированных примеров маршрутов. Я советую почитать его
как-нибудь, а также взглянуть на Rails Guides article “Rails Routing from the outside in” (# перевод этой статьи, а также многих других из данного руководства можно найти на сайте http://www.rusrails.ru/) для более углубленного изучения маршрутов. Сейчас, однако, мы будем придерживаться примеров в Листинге 5.18.9
Листинг 5.18. Маршруты для статических страниц.
config/routes.rb
SampleApp::Application.routes.draw do
match '/contact', :to => 'pages#contact'
match '/about', :to => 'pages#about'
match '/help', :to => 'pages#help'
.
.
.
end
contact, about, и help страниц; маршрутом для home страницы мы озаботимся в Листинге 5.20. (Раз уж мы будем пользоваться маршрутами из Листинга 5.18 исключительно с этого момента, мы воспользуемся этой возможностью чтобы удалить маршруты контроллера Pages (get "pages/home", и т.д.) последний раз мы их видели в Листинге 3.17.)Если вы вчитаетесь в код Листинга 5.18 повнимательнее, вы, вероятно, сможете понять что он делает; например, вы можете видеть, что
match '/about', :to => 'pages#about'
’/about’ и направляет его к about действию контроллера Pages. До этого было более четко: мы использовали get ’pages/about’ чтобы попасть в то же место, но /about более кратко. Не очевидным является то, что match ’/about’ также автоматически создает именованные маршруты для использования в контроллерах и представлениях:about_path => '/about'
about_url => 'http://localhost:3000/about'
about_url это полный URL http://localhost:3000/about (localhost:3000 заменится на доменное имя, например example.com, при полном развертывании сайта). Как уже говорилось в Разделе 5.2, чтобы получить только /about, вы используете about_path. (Rails Tutorial использует path форму по соглашению, но разница редко имеет значение на практике (# т.е также возможно применение _url формы).)С помощью этих маршрутов, теперь определенных, тесты для About, Contact, и Help страниц должны пройти (Как обычно, используйте Autotest или
rspec spec/ для проверки.) Кроме теста для Home страницы.Чтобы установить соответствие маршрута для домашней страницы, мы могли бы использовать код подобный этому:
match '/', :to => 'pages#home'
Листинг 5.19. Закомментированная подсказка для определения root маршрута.
config/routes.rb
SampleApp::Application.routes.draw do
.
.
.
# You can have the root of your site routed with "root"
# just remember to delete public/index.html.
# root :to => "welcome#index"
.
.
.
end
Листинг 5.20. Добавление соответствия для root маршрута.
config/routes.rb
SampleApp::Application.routes.draw do
match '/contact', :to => 'pages#contact'
match '/about', :to => 'pages#about'
match '/help', :to => 'pages#help'
root :to => 'pages#home'
.
.
.
end
root_path => '/'
root_url => 'http://localhost:3000/'
public/index.html чтобы предотвратить отображение дефолтной страницы (Рис. 1.3) при посещении /. Конечно, вы можете просто удалить файл выполненив Move to trash
в текстовом редакторе, но если вы используете Git для контроля версий,
есть способ удалить файл и в тоже время сообщить Git об удалени — с
помощью git rm:$ git rm public/index.html
$ git commit -am "Removed default Rails page"
git commit -a -m "Message", с флагами для “все изменения” (-a) и сообщения (-m). Как показано выше, Git также позволяет скрутить два флага в один git commit -am "Message".При этом, все маршруты для статических страниц работают, и тесты должны пройти. Теперь мы просто должны заполнить ссылки в макете.
5.2.3 Именованные маршруты
Давайте применим именованные маршруты, созданные в Разделе 5.2.2. Это повлечет за собой заполнение второго аргументаlink_to функции правильным именованным маршрутом. Например, мы конвертируем<%= link_to "About", '#' %>
<%= link_to "About", about_path %>
Мы начнем с партиала шапки,
_header.html.erb (Листинг 5.21),
который содержит ссылки на Home и Help страницы. Пока мы здесь, мы
также, следуя общей конвенции Сети, свяжем логотип с Home страницей.
Листинг 5.21. Партиал шапки со ссылками.
app/views/layouts/_header.html.erb
<header>
<% logo = image_tag("logo.png", :alt => "Sample App", :class => "round") %>
<%= link_to logo, root_path %>
<nav class="round">
<ul>
<li><%= link_to "Home", root_path %></li>
<li><%= link_to "Help", help_path %></li>
<li><%= link_to "Sign in", '#' %></li>
</ul>
</nav>
</header>
’#’. Обратите внимание, что этот код определяет локальную переменную logo для тега логотипа, а затем делает ссылку на него в следующей строке: <% logo = image_tag("logo.png", :alt => "Sample App", :class => "round") %>
<%= link_to logo, root_path %>
logo помощника; см. Раздел 5.5.)Другим местом со ссылками является подвал,
_footer.html.erb, в котором есть ссылки для About и Contact страниц (Листинг 5.22).
Листинг 5.22. Частичный шаблон подвала со ссылками.
app/views/layouts/_footer.html.erb
<footer>
<nav class="round">
<ul>
<li><%= link_to "About", about_path %></li>
<li><%= link_to "Contact", contact_path %></li>
<li><a href="http://news.railstutorial.org/">News</a></li>
<li><a href="http://www.railstutorial.org/">Rails Tutorial</a></li>
</ul>
</nav>
</footer>
Кстати, стоит отметить, что мы на самом деле не протестировали на наличие ссылок в шаблоне, наши тесты будут провальными, только если маршруты не определены. Вы можете проверить это, закомментировав один из маршрутов в Листинге 5.18 и выполнив тесты. Метод тестирования, который на самом деле обеспечивает уверенность что ссылки существуют и отправляют в правильные места, см. Разделе 5.5.
Рисунок 5.9: About страница на /about (полный размер)
5.3 Регистрация пользователей: первый шаг
В качестве кульминации нашей работы над макетом и маршрутами, в этом разделе мы сделаем маршрут для страницы регистрации (signup), что будет означать создание второго контроллера. Это первый важный шаг к предоставлению пользователям возможности регистрироваться на нашем сайте, мы сделаем следующий шаг, моделирование пользователя, в Главе 6, и мы закончим работу в Главе 8.5.3.1 Users контроллер
Мы создали наш первый контроллер Pages, еще в Разделе 3.1.2. Пришло время создать второй — контроллер Users. Как и прежде, мы будем использоватьgenerate
для создания простейшего контроллер, который отвечает нашим текущим
потребностям, а именно, с одной страницей-заглушкой для регистрации
новых пользователей. Следуя конвенции REST архитектуры предпочитаемой Рельсами, мы назовем действие для новых пользователей, new и передадим его в качестве аргумента в generate controller для создания его (действия) автоматически (Листинг 5.23).
Листинг 5.23. Генерация контроллера Users (с
new действием). $ rails generate controller Users new
create app/controllers/users_controller.rb
route get "users/new"
invoke erb
create app/views/users
create app/views/users/new.html.erb
invoke rspec
create spec/controllers/users_controller_spec.rb
create spec/views/users
create spec/views/users/new.html.erb_spec.rb
invoke helper
create app/helpers/users_helper.rb
invoke rspec
create spec/helpers/users_helper_spec.rb
$ rm -rf spec/views
$ rm -rf spec/helpers
Листинг 5.24. Тестирование signup страницы.
spec/controllers/users_controller_spec.rb
require 'spec_helper'
describe UsersController do
describe "GET 'new'" do
it "should be successful" do
get 'new'
response.should be_success
end
end
end
new действие и new.html.erb представление, чтобы пройти этот тест (Листинг 5.25). (Для просмотра страницы /users/new, вам может потребоваться перезагрузка сервера.)
Листинг 5.25. Действие для страницы "новый пользователь" (signup).
app/controllers/users_controller.rb
class UsersController < ApplicationController
def new
end
end
"Sign up" (Листинг 5.26). Не забудьте добавить render_views как мы это делали в Pages контроллере spec (Листинг 3.20); в противном случае, тест не пройдет, даже после того как мы добавим правильный заголовок (тайтл).
Листинг 5.26. Тест для заголовка signup страницы.
spec/controllers/users_controller_spec.rb
require 'spec_helper'
describe UsersController do
render_views
describe "GET 'new'" do
it "should be successful" do
get 'new'
response.should be_success
end
it "should have the right title" do
get 'new'
response.should have_selector("title", :content => "Sign up")
end
end
end
have_selector метод (который мы видели ранее (Раздел 3.3.1); отмечу, что как и в Разделе 3.3.1, have_selector нуждается в render_views строке чтобы он мог тестировать представления вместе с действиями.Конечно, по задумке этот тест сейчас провальный (Красный). Чтобы создать пользовательский заголовок, нам нужно сделать
@title переменную экземпляра как в Разделе 3.3.3.Таким образом, мы можем получить Зеленый с кодом в Листинге 5.27.
Листинг 5.27. Назначение пользовательского заголовка для new user страницы.
app/controllers/users_controller.rb
class UsersController < ApplicationController
def new
@title = "Sign up"
end
end
5.3.2 Signup URL
С кодом из Раздела 5.3.1, мы уже имеем работающую страницу для нового пользователя на /users/new, но вспомним из Таблицы 5.1 что мы хотим, чтобы вместо него был URL /signup. Как и в Разделе 5.2, мы вначале напишем тест (Листинг 5.28).
Листинг 5.28. Простой интеграционный тест для user signup ссылки.
spec/requests/layout_links_spec.rb
require 'spec_helper'
describe "LayoutLinks" do
.
.
.
it "should have a signup page at '/signup'" do
get '/signup'
response.should have_selector('title', :content => "Sign up")
end
end
Последний шаг это создание именованного маршрута для регистрации. Мы будем следовать примерам из Листинга 5.18 и добавим
match ’/signup’ правило для signup URL (Листинг 5.29).
Листинг 5.29. Маршрут для страницы регистрации.
config/routes.rb
SampleApp::Application.routes.draw do
get "users/new"
match '/signup', :to => 'users#new'
match '/contact', :to => 'pages#contact'
match '/about', :to => 'pages#about'
match '/help', :to => 'pages#help'
root :to => 'pages#home'
.
.
.
end
get "users/new", которое было сгенерированно автоматически при создании Users контроллера в Листинге 5.23. В настоящее время это правило необходимо для работы роутинга /users/new правильному, но не соответствующему REST конвенции (Таблица 2.2), и мы ликвидируем его в Разделе 6.3.3.В этой точке тест для регистрации из Листинга 5.28 должен пройти. Все, что осталось, это добавить правильную ссылку к кнопке на главной странице. Как и с другими маршрутами,
match ’/signup’ дает нам именованный маршрут signup_path, который мы поместим для использования в Листинге 5.30.
Листинг 5.30. Добавление ссылки к кнопке Signup страницы.
app/views/pages/home.html.erb
<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>
<%= link_to "Sign up now!", signup_path, :class => "signup_button round" %>
Рисунок 5.10: Новая signup страница на /signup. (полный размер)
5.4 Заключение
В этой главе мы привели шаблон нашего приложение в чувство и отполировали маршруты. Остальная часть книги посвящена конкретизации примера приложения: во-первых, путем добавления пользователей, которые могут зарегистрироваться, войти в систему и выйти; затем добавлением пользовательских микросообщений и, наконец, добавлением пользовательских взаимоотношений.Если вы используете Git, убедитесь, что зафиксировали и объединили изменения (и, просто чтобы быть параноиком, запустите тесты в первую очередь):
$ bundle exec rspec spec/
$ git add .
$ git commit -m "Finished layout and routes"
$ git checkout master
$ git merge filling-in-layout
$ git push
$ git push heroku
5.5 Упражнения
- Заменить локальную переменную
logoв Листинге 5.21 на вспомогательный метод с тем же названием, так чтобы новый частичный шаблон выглядел как Листинг 5.31. Используйте код из Листинга 5.32 чтобы начать работу. - Возможно, вы заметили, что наши тесты для ссылок шаблона тестируют
маршруты, но на самом деле не проверяют, ведут ли ссылки к правильным
страницам. Один из способов реализации этих испытаний заключается в
использовании
visitиclick_linkвнутри RSpec интеграционного теста. Дополните код из Листинга 5.33 чтобы проверить что все ссылки шаблона правильно определены.
Листинг 5.31. Партиал шапки с помощником logo из Листинга 5.32.
app/views/layouts/_header.html.erb
<header>
<%= link_to logo, root_path %>
<nav class="round">
<ul>
<li><%= link_to "Home", root_path %></li>
<li><%= link_to "Help", help_path %></li>
<li><%= link_to "Sign in", '#' %></li>
</ul>
</nav>
</header>
Листинг 5.32. Образец для помощника
logo app/helpers/application_helper.rb
module ApplicationHelper
def logo
# Fill in.
end
# Return a title on a per-page basis.
def title
.
.
.
end
end
Листинг 5.33. Тесты для ссылок в шаблоне.
spec/requests/layout_links_spec.rb
require 'spec_helper'
describe "LayoutLinks" do
.
.
.
it "should have the right links on the layout" do
visit root_path
click_link "About"
response.should have_selector('title', :content => "About")
click_link "Help"
response.should # fill in
click_link "Contact"
response.should # fill in
click_link "Home"
response.should # fill in
click_link "Sign up now!"
response.should # fill in
end
end
- Макеты в Ruby on Rails Tutorial сделаны с помощью замечательного онлайн приложения для создания макетов, называемого Mockingbird. ↑
- Они абсолютно не связаны с классами Ruby. ↑
- Вы моли заметить, что
imgtag, вместо сходства с <img>...</img>, более похож на <img ... />. Теги, соответствующие этой форме, известны как самозакрывающиеся. ↑ altтекст также, будет выведен на экран средствами чтения с экрана для людей со слабым зрением. Хотя люди иногда неаккуратны при включенииaltатрибута для изображений, фактически, это требуется HTML стандартом. К счастью, Rails включает дефолтныйaltатрибут; если вы не укажете значение атрибута, в названииimage_tag, Rails просто будет использовать имя файла изображения (за вычетом расширения). В этом случае, тем не менее,Sample Appявляется более дескриптивным чемlogo, таким образом я предпочел указатьaltтекст явно. ↑- Отметьте, что пользователи Chrome и Safari будут видеть индикатор поврежденного изображения, вместо альтернативного текста “Sample App”. ↑
- Цвета HTML могут быть кодированы тремя основными 16
(шестнадцатеричными) числами, каждое из которых обозначает один из трех
основных цветов, Красный, Зеленый, и Синий.
#fffэто максимум всех трех цветов, что приводит к чистому белому. За подробностями обращайтесь на сайт HTML colors. ↑ - Blueprint CSS испльзует сетку из столбцов шириной 40 пикселей, 30 пикселей для самого столбца и 10 пикселей отступа. Самый правый столбец в отступе не нуждается, таким образом, 18 столбцов это 710 пикселей: 18 * 40 – 10 = 710. ↑
- Многие Rails разработчики используют
sharedдиректорию для партиалов совместно используемых разными представлениями. Я предпочитаю использоватьsharedпапку для "служебных" партиалов которые используются во множестве страниц, помещая партиалы, которые используются буквально на каждой странице (такие как части шаблона сайта) вlayoutsдиректорию. (Мы создадимsharedдиректорию в Главе 8.) Это кажется мне более логичным, но помещение всех партиалов в папкуsharedтоже замечательно работает. ↑ - В строке
SampleApp::Application.routes.draw doвы могли распознать, чтоdrawметод берет block, конструкцию, которую мы видели в Разделе 4.3.2. ↑
Комментариев нет:
Отправить комментарий