Ruby on Rails Tutorial

Изучение Rails на Примерах

Майкл Хартл

Содержание

  1. Предисловие к русскому изданию
  2. Глава 1 От нуля к развертыванию
    1. 1.1 Введение
      1. 1.1.1 Комментарии для разных читателей
      2. 1.1.2 “Масштабирование” Rails
      3. 1.1.3 Соглашения в этой книге
    2. 1.2 За работу
      1. 1.2.1 Среда разработки
        1. Интегрированные Среды Разработки
        2. Текстовые редакторы и инструменты командной строки
        3. Браузеры
        4. Примечание об инструментах
      2. 1.2.2 Ruby, RubyGems, Rails и Git
        1. Rails Installer (Windows)
        2. Установка Git
        3. Установка Ruby
        4. Установка RubyGems
        5. Установка Rails
      3. 1.2.3 Первое приложение
      4. 1.2.4 Bundler
      5. 1.2.5 rails server
      6. 1.2.6 Модель-представление-контроллер (MVC)
    3. 1.3 Управление версиями с Git
      1. 1.3.1 Установка и настройка
        1. Первоначальная настройка системы
        2. Первоначальная настройка репозитория
      2. 1.3.2 Добавление и фиксация
      3. 1.3.3 Что хорошего Git делает для вас?
      4. 1.3.4 GitHub
      5. 1.3.5 Ветвление, редактирование, фиксация, объединение
        1. Ветвление
        2. Редактирование
        3. Фиксация
        4. Объединение
        5. Отправка
    4. 1.4 Развертывание
      1. 1.4.1 Установка Heroku
      2. 1.4.2 Развертывание на Heroku, шаг первый
      3. 1.4.3 Развертывание на Heroku, шаг второй
      4. 1.4.4 Команды Heroku
    5. 1.5 Заключение
  3. Глава 2 demo app
    1. 2.1 Планирование приложения
      1. 2.1.1 Моделирование пользователей
      2. 2.1.2 Моделирование микросообщений
    2. 2.2 Ресурс Users
      1. 2.2.1 Обзор пользователя
      2. 2.2.2 MVC в действии
      3. 2.2.3 Недостатки данного ресурса Users
    3. 2.3 Ресурс Microposts
      1. 2.3.1 Микрообзор микросообщений
      2. 2.3.2 Помещение micro в микросообщения
      3. 2.3.3 Пользователь has_many микросообщений
      4. 2.3.4 Иерархия наследования
      5. 2.3.5 Развертывание демонстрационного приложения
    4. 2.4 Заключение
  4. Глава 3 В основном статические страницы
    1. 3.1 Статические страницы
    2. 3.2 Наши первые тесты
      1. 3.2.1 Разработка через тестирование
      2. 3.2.2 Добавление страницы
        1. Красный
        2. Зеленый
        3. Refactor (реорганизация)
    3. 3.3 Немного динамические страницы
      1. 3.3.1 Тестирование изменения заголовка
      2. 3.3.2 Прохождение тестов заголовка
      3. 3.3.3 Встроенный Ruby
      4. 3.3.4 Устранение дублирования шаблонами
    4. 3.4 Заключение
    5. 3.5 Упражнения
    6. 3.6 Продвинутые настройки
      1. 3.6.1 Избавляемся от bundle exec
        1. RVM Bundler интеграция
        2. binstubs
      2. 3.6.2 Автоматизируем тесты с Guard
      3. 3.6.3 Ускоряем тесты с помощью Spork
        1. Guard и Spork
      4. 3.6.4 Запускаем тесты внутри Sublime Text
  5. Глава 4 Rails-приправленный Ruby
    1. 4.1 Причины
    2. 4.2 Строки и методы
      1. 4.2.1 Комментарии
      2. 4.2.2 Строки
        1. Вывод на экран
        2. Строки в одинарных кавычках
      3. 4.2.3 Объекты и передача сообщений
      4. 4.2.4 Определение методов
      5. 4.2.5 Возвращение к title хелперу
    3. 4.3 Другие структуры данных
      1. 4.3.1 Массивы и диапазоны
      2. 4.3.2 Блоки
      3. 4.3.3 Хэши и символы
      4. 4.3.4 Вновь CSS
    4. 4.4 Ruby классы
      1. 4.4.1 Конструкторы
      2. 4.4.2 Наследование классов
      3. 4.4.3 Изменение встроенных классов
      4. 4.4.4 Класс контроллер
      5. 4.4.5 Класс User
    5. 4.5 Заключение
    6. 4.6 Упражнения
  6. Глава 5 Заполнение шаблона
    1. 5.1 Добавление некоторых структур
      1. 5.1.1 Навигация по сайту
      2. 5.1.2 Bootstrap и кастомные CSS
      3. 5.1.3 Частичные шаблоны (partials)
    2. 5.2 Sass и файлопровод (asset pipeline)
      1. 5.2.1 Файлопровод
        1. Директории ассетов
        2. Файлы-манифесты
        3. Препроцессоры
        4. Производительность в продакшен
      2. 5.2.2 Синтаксически обалденные таблицы стилей
        1. Вложение
        2. Переменные
    3. 5.3 Ссылки в шаблоне
      1. 5.3.1 Тестирование маршрутов
      2. 5.3.2 Rails маршруты
      3. 5.3.3 Именованные маршруты
      4. 5.3.4 Приятный RSpec
    4. 5.4 Регистрация пользователей: Первый шаг
      1. 5.4.1 Контроллер Users
      2. 5.4.2 URL для регистрации
    5. 5.5 Заключение
    6. 5.6 Упражнения
  7. Глава 6 Моделирование пользователей
    1. 6.1 Модель User
      1. 6.1.1 Миграции базы данных
      2. 6.1.2 Файл модели
      3. 6.1.3 Создание объектов user
      4. 6.1.4 Поиск объектов user
      5. 6.1.5 Обновление объектов user
    2. 6.2 Валидации User
      1. 6.2.1 Начальные тесты для пользователей
      2. 6.2.2 Валидация наличия
      3. 6.2.3 Валидация длины
      4. 6.2.4 Валидация формата
      5. 6.2.5 Валидация уникальности
        1. Предостережение уникальности
    3. 6.3 Добавление безопасного пароля
      1. 6.3.1 Зашифрованный пароль
      2. 6.3.2 Пароль и подтверждение
      3. 6.3.3 Аутентификация пользователя
      4. 6.3.4 У пользователя есть безопасный пароль
      5. 6.3.5 Создание пользователя
    4. 6.4 Заключение
    5. 6.5 Упражнения
  8. Chapter 7 Регистрация
    1. 7.1 Демонстрация пользователей
      1. 7.1.1 Отладка и окружения Rails
      2. 7.1.2 A Ресурс Users
      3. 7.1.3 Тестирование страницы показывающей пользователя (с фабриками)
      4. 7.1.4 Изображение Gravatar и боковая панель
    2. 7.2 Форма регистрации
      1. 7.2.1 Тесты для регистрации пользователя
      2. 7.2.2 Применение form_for
      3. 7.2.3 HTML формы
    3. 7.3 Провальная регистрация
      1. 7.3.1 Рабочая форма
      2. 7.3.2 Строгие параметры
      3. 7.3.3 Сообщения об ошибках при регистрации
    4. 7.4 Успешная регистрация
      1. 7.4.1 Завершенная форма регистрации
      2. 7.4.2 Флэш
      3. 7.4.3 Первая регистрация
      4. 7.4.4 Развертывание приложения на сервере с SSL
    5. 7.5 Заключение
    6. 7.6 Упражнения
  9. Глава 8 Войти, выйти
    1. 8.1 Сессии и провальный вход
      1. 8.1.1 Sessions контроллер
      2. 8.1.2 Тестирование входа
      3. 8.1.3 Форма для входа
      4. 8.1.4 Обзор отправки формы
      5. 8.1.5 Рендеринг с флэш сообщением
    2. 8.2 Успешный вход
      1. 8.2.1 Запомнить меня
      2. 8.2.2 Рабочий метод sign_in
      3. 8.2.3 Текущий пользователь
      4. 8.2.4 Изменение ссылок шаблона
      5. 8.2.5 Вход после регистрации
      6. 8.2.6 Выход
    3. 8.3 Введение в Cucumber (опционально)
      1. 8.3.1 Установка и настройка
      2. 8.3.2 Фичи и шаги
      3. 8.3.3 Контрапункт: кастомные проверки RSpec
    4. 8.4 Заключение
    5. 8.5 Упражнения
  10. Глава 9 Обновление, демонстрация и удаление пользователей
    1. 9.1 Обновление пользователей
      1. 9.1.1 Форма для редактирования
      2. 9.1.2 Провальное редактирование
      3. 9.1.3 Успешное редактирование
    2. 9.2 Авторизация
      1. 9.2.1 Требование входа пользователей
      2. 9.2.2 Требование правильного пользователя
      3. 9.2.3 Дружелюбная переадресация
    3. 9.3 Отображение всех пользователей
      1. 9.3.1 Список пользователей
      2. 9.3.2 Образцы пользователей
      3. 9.3.3 Пагинация
      4. 9.3.4 Частичный рефакторинг
    4. 9.4 Уничтожение пользователей
      1. 9.4.1 Административные пользователи
        1. Возвращение к строгим параметрам
      2. 9.4.2 Destroy действие
    5. 9.5 Заключение
    6. 9.6 Упражнения
  11. Глава 10 Микросообщения пользователей
    1. 10.1 Модель Micropost
      1. 10.1.1 Базовая модель
      2. 10.1.2 Первая валидация
      3. 10.1.3 Ассоциации Пользователь/Микросообщения
      4. 10.1.4 Улучшение микросообщений
        1. Дефолтное пространство (scope)
        2. Dependent: destroy
      5. 10.1.5 Валидации контента
    2. 10.2 Просмотр микросообщений
      1. 10.2.1 Дополнение страницы показывающей пользователя
      2. 10.2.2 Образцы микросообщений
    3. 10.3 Манипулирование микросообщениями
      1. 10.3.1 Контроль доступа
      2. 10.3.2 Создание микросообщений
      3. 10.3.3 Предварительная реализация потока сообщений
      4. 10.3.4 Уничтожение микросообщений
    4. 10.4 Заключение
    5. 10.5 Упражнения
  12. Глава 11 Слежение за сообщениями пользователей
    1. 11.1 Модель Relationship
      1. 11.1.1 Проблема с моделью данных (и ее решение)
      2. 11.1.2 Ассоциации пользователь/взаимоотношение
      3. 11.1.3 Валидации
      4. 11.1.4 Читаемые пользователи
      5. 11.1.5 Читатели пользователя
    2. 11.2 Веб-интерфейс для читаемых пользователей
      1. 11.2.1 Образцы данных
      2. 11.2.2 Статистика и форма для слежения за сообщениями пользователя
      3. 11.2.3 Страницы с читаемыми и читателями
      4. 11.2.4 Стандартный способ реализации кнопки "читать" (follow)
      5. 11.2.5 Реализация кнопки "читать" (follow) с Ajax
    3. 11.3 Поток сообщений
      1. 11.3.1 Мотивация и стратегия
      2. 11.3.2 Первая реализация потока сообщений
      3. 11.3.3 Подзапросы
      4. 11.3.4 Новый поток сообщений
    4. 11.4 Заключение
      1. 11.4.1 Расширения к примеру приложения
        1. Реплики
        2. Обмен сообщениями
        3. Уведомления о новых читателях
        4. Напоминание пароля
        5. Подтверждение регистрации
        6. RSS канал
        7. REST API
        8. Поиск
      2. 11.4.2 Руководство по дальнейшим ресурсам
    5. 11.5 Упражнения

Предисловие

Моя компания (CD Baby) была одной из первых громко перешедших на Ruby on Rails, а затем еще громче вернувшейся обратно на PHP (Google расскажет вам об этой драме). Эту книгу, написанную Майклом Хартлом так высоко рекомендовали, что я должен был попробовать её, и Ruby on Rails Tutorial это всё, что я использовал, чтобы вернуться к Rails.

Хотя я уже прошел через много книг по Rails, это одна из немногих, что, наконец, зацепила меня. Было много написано книг типа «Путь Rails» — после которых я чувствовал себя неестественно, но после этой книги я наконец почувствовал себя естественно. Это также единственная книга по Rails, которая соблюдает методику «разработка через тестирование» на всем своем протяжении, этот подход строго рекомендуется специалистами, но он никогда не был так чётко продемонстрирован ранее. Наконец, Git, GitHub и Heroku присутствуют в демо-примерах, автор действительно дает вам почувствовать, что он хотел сделать реальный проект. Учебный код примеров не изолирован.

Линейное повествование — отличный формат. Лично я прошел Rails Tutorial в течении трёх долгих дней, делая все примеры и задачи в конце каждой главы. Делайте всё от начала до конца, не прыгая, и вы получите максимальную пользу.

Наслаждайтесь!

Derek Sivers (sivers.org)
Основатель CD Baby

Благодарности

Ruby On Rails Учебник во многом обязан моей предыдущей книге по Rails, RailsSpace и, следовательно, моему соавтору Aurelius Prochazka. Я хотел бы поблагодарить Aure как за работу, которую он проделал над прошлой книгой, так и за поддержку этой. Я также хотел бы поблагодарить Debra Williams Cauley, редактора обеих книг RailsSpace и Rails Tutorial; до тех пор, пока она не прекратит брать меня на бейсбол, я буду продолжать писать книги для нее.

Я хотел бы поблагодарить огромное количество Рубистов учивших и вдохновлявших меня на протяжении многих лет: David Heinemeier Hansson, Yehuda Katz, Carl Lerche, Jeremy Kemper, Xavier Noria, Ryan Bates, Geoffrey Grosenbach, Peter Cooper, Matt Aimonetti, Gregg Pollack, Wayne E. Seguin, Amy Hoy, Dave Chelimsky, Pat Maddox, Tom Preston-Werner, Chris Wanstrath, Chad Fowler, Josh Susser, Obie Fernandez, Ian McFarland, Steven Bristol, Pratik Naik, Sarah Mei, Sarah Allen, Wolfram Arnold, Alex Chaffee, Giles Bowkett, Evan Dorn, Long Nguyen, James Lindenbaum, Adam Wiggins, Tikhon Bernstam, Ron Evans, Wyatt Greene, Miles Forrest, хороших людей из Pivotal Labs, команду Heroku, thoughtbot ребят, и команду GitHub. Наконец, многих, многих читателей - слишком много чтобы перечислять их здесь - внёсших большое количество предложений по улучшению и сообщивших об ошибках во время написания этой книги, и я с благодарностью признаю их помощь в написании ее настолько хорошей, насколько это было возможно.

Об авторе

Майкл Хартл – автор Ruby on Rails Tutorial, лидирующего введения в веб разработку на Ruby on Rails. Его предыдущий опыт включает в себя написание и разработку RailsSpace - чрезвычайно устаревшего учебника по Rails и разработку Insoshi - некогда популярной, а ныне устаревшей платформы для социальных сетей написанной на Ruby on Rails. В 2011, Майкл получил Ruby Hero Award за его вклад в Ruby сообщество. Он закончил Harvard College, имеет степень Кандидата Физических Наук присвоенную в Caltech и является выпускником предпринимательских курсов Y Combinator.

Копирайт и лицензия

Ruby on Rails Tutorial: Learn Web Development with Rails. Copyright © 2012 by Michael Hartl. Весь исходный код в Ruby on Rails Tutorial доступен под MIT License и Beerware License.

Лицензия MIT

Copyright (c) 2013 Michael Hartl

Данная лицензия разрешает лицам, получившим копию данного программного
обеспечения и сопутствующей документации (в дальнейшем именуемыми
«Программное Обеспечение»), безвозмездно использовать Программное
Обеспечение без ограничений, включая неограниченное право на использование,
копирование, изменение, добавление, публикацию, распространение,
сублицензирование и/или продажу копий Программного Обеспечения, также
как и лицам, которым предоставляется данное Программное Обеспечение,
при соблюдении следующих условий:

Указанное выше уведомление об авторском праве и данные условия должны быть
включены во все копии или значимые части данного Программного Обеспечения.

ДАННОЕ ПРОГРАММНОЕ ОБЕСПЕЧЕНИЕ ПРЕДОСТАВЛЯЕТСЯ «КАК ЕСТЬ», БЕЗ КАКИХ-ЛИБО
ГАРАНТИЙ, ЯВНО ВЫРАЖЕННЫХ ИЛИ ПОДРАЗУМЕВАЕМЫХ, ВКЛЮЧАЯ, НО НЕ ОГРАНИЧИВАЯСЬ
ГАРАНТИЯМИ ТОВАРНОЙ ПРИГОДНОСТИ, СООТВЕТСТВИЯ ПО ЕГО КОНКРЕТНОМУ НАЗНАЧЕНИЮ И
ОТСУТСТВИЯ НАРУШЕНИЙ ПРАВ. НИ В КАКОМ СЛУЧАЕ АВТОРЫ ИЛИ ПРАВООБЛАДАТЕЛИ НЕ
НЕСУТ ОТВЕТСТВЕННОСТИ ПО ИСКАМ О ВОЗМЕЩЕНИИ УЩЕРБА, УБЫТКОВ ИЛИ ДРУГИХ
ТРЕБОВАНИЙ ПО ДЕЙСТВУЮЩИМ КОНТРАКТАМ, ДЕЛИКТАМ ИЛИ ИНОМУ, ВОЗНИКШИМ ИЗ,
ИМЕЮЩИМ ПРИЧИНОЙ ИЛИ СВЯЗАННЫМ С ПРОГРАММНЫМ ОБЕСПЕЧЕНИЕМ ИЛИ ИСПОЛЬЗОВАНИЕМ
ПРОГРАММНОГО ОБЕСПЕЧЕНИЯ ИЛИ ИНЫМИ ДЕЙСТВИЯМИ С ПРОГРАММНЫМ ОБЕСПЕЧЕНИЕМ.
/*
 * ----------------------------------------------------------------------------
 * "ПИВНАЯ ЛИЦЕНЗИЯ" (Ревизия 42):
 * Весь код написан Майклом Хартлом. До тех пор пока вы осознаете это,
 * вы можете делать с ним все что захотите. Если мы когда нибудь
 * встретимся, и если это того стоило, вы можете купить мне
 * пиво в ответ.
 * ----------------------------------------------------------------------------
 */

Глава 2 demo app

В этой главе мы разработаем простое демонстрационное приложение, чтобы показать мощь Rails. Цель - получить общее представление о программировании на Ruby on Rails (и веб-разработке в целом), быстро сгенерировав приложение, используя scaffold generators. Как обсуждалось в Блоке 1.2, остальная часть книги будет применять противоположный подход, постепенно разрабатывая приложение с объяснением всех новых понятий по мере их появления, но для быстрого обзора (и некоторого быстрорастворимого удовлетворения) нет ничего лучше чем scaffolding. Конечное демонстрационное приложение позволит нам взаимодействовать с ним через свои URL, дав нам понимание структуры Rails приложений, включая первый пример REST архитектуры предпочитаемой Rails.

Как и предстоящий пример приложения, демонстрационное приложение будет состоять из пользователей и связанных с ними микросообщений (образуя минималистичное приложение в стиле Twitter). Функциональность будет совершенно слаборазвита и многие из шагов будут походить на волшебство, но не переживайте: полный пример приложения разработает подобное же приложение с нуля, начиная с Главы 3, и я дам многочисленные ссылки на более поздний материал. Тем временем, имейте терпение и немного веры - все таки основная цель данного учебника - удержать вас вне этого поверхностного, управляемого scaffold подхода, для достижения более глубокого понимания Rails.

2.1 Планирование приложения

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

$ cd ~/rails_projects
$ rails new demo_app
$ cd demo_app

Затем, мы используем текстовый редактор, чтобы обновить Gemfile необходимый Bundler, содержанием из Листинга 2.1.

Листинг 2.1. Gemfile для демонстрационного приложения.
source 'https://rubygems.org'
ruby '2.0.0'
#ruby-gemset=railstutorial_rails_4_0

gem 'rails', '4.0.2'

group :development do
  gem 'sqlite3', '1.3.8'
end

gem 'sass-rails', '4.0.1'
gem 'uglifier', '2.1.1'
gem 'coffee-rails', '4.0.1'
gem 'jquery-rails', '3.0.4'
gem 'turbolinks', '1.1.1'
gem 'jbuilder', '1.0.2'

group :doc do
  gem 'sdoc', '0.3.20', require: false
end

group :production do
  gem 'pg', '0.15.1'
  gem 'rails_12factor', '0.0.2'
end

Отмечу, что Листинг 2.1 аналогичен Листингу 1.9

Как и в Разделе 1.4.1, мы установим локальные гемы и предотвратим установку production гемов с помощью опции --without production:

$ bundle install --without production
$ bundle update
$ bundle install

(Напомним что если Bundler выдает ошибку связанную с readline, стОит попробовать добавить gem ’rb-readline’ в ваш Gemfile.)

Наконец, мы поместим наш код в систему контроля версий. Вспомним что rails команда генерирует дефолтный .gitignore файл, но, в зависимости от вашей системы, вы можете найти расширенный файл из Листинга 1.7 гораздо более удобным. Затем инициализируем Git репозиторий и делаем первый коммит:

$ git init
$ git add .
$ git commit -m "Initial commit"
create_demo_repo_4_0
Рисунок 2.1: Создание репозитория demo app на GitHub. (полный размер)

Можно также дополнительно создать новый репозиторий (Рис. 2.1) и отправить его на GitHub:

$ git remote add origin https://github.com/<username>/demo_app.git
$ git push -u origin master

(Как и в случае с первым приложением, позаботьтесь о том чтобы не инициализировать репозиторий GitHub с файлом README.)

Теперь мы готовы начать делать само приложение. Типичный первый шаг, при разработке приложений это создание модели данных, которая является изображением структур, необходимых нашему приложению. В нашем случае demo app будет упрощенным микроблогом: только пользователи и короткие (микро) сообщения. Таким образом, мы начнем с модели для пользователей приложения (Раздел 2.1.1), затем мы добавим модель для микросообщений (Раздел 2.1.2).

2.1.1 Моделирование пользователей

Вариантов для модели данных пользователя так же много, как много различных форм регистрации в сети; мы пойдем отчетливо минималистичным путем. У пользователей нашего demo app будет уникальный целочисленный идентификатор называемый id, публично видимое имя (тип - string (строка)), и email адрес (также string) совпадающий с именем пользователя. Итоговая модель данных для пользователей представлена на Рис. 2.2.

demo_user_model
Рис. 2.2: Модель данных для пользователей.

Как мы увидим в Разделе 6.1.1, табличка users в Рис. 2.2 соответствует таблице в базе данных и id, name, и email атрибуты это столбцы этой таблицы.

2.1.2 Моделирование микросообщений

Ядро модели данных микросообщений даже проще чем для пользователей: микросообщение имеет только id и поле content для текста микросообщения (тип- string).1 Есть дополнительная сложность: мы хотим связать каждое микросообщение с определенным пользователем; мы выполним это, записывая user_id владельца сообщения. Результаты показаны на Рис. 2.3.

demo_micropost_model
Рис. 2.3: Модель данных для микросообщений.

Мы увидим в Разделе 2.3.3 (и более полно в Главе 10) как этот user_id атрибут позволит нам кратко реализовать идею, что у пользователя потенциально есть много связанных с ним микросообщений.

2.2 Ресурс Users

В этом разделе мы реализуем модель данных пользователей из Раздела 2.1.1, наряду с веб-интерфейсом к этой модели. Эта комбинация образует ресурс Users, который позволит нам думать о пользователях как об объектах, которые могут быть созданы, считаны, обновлены, и удалены через сеть с использованием HTTP протокола. Как обещалось во введении, наш ресурс Users будет создаваться программой scaffold generator, которая стандартно поставляется с каждым проектом Rails. Я настоятельно прошу вас не всматриваться в генерируемый код; на этом этапе он лишь запутает вас.

Rails scaffolding запускается передачей scaffold команды скрипту rails generate. Аргумент команды scaffold это имя ресурса в единственном числе (в данном случае, User), вместе с дополнительными параметрами для атрибутов модели данных:2

$ rails generate scaffold User name:string email:string
      invoke  active_record
      create    db/migrate/20130305221714_create_users.rb
      create    app/models/user.rb
      invoke    test_unit
      create      test/models/user_test.rb
      create      test/fixtures/users.yml
      invoke  resource_route
       route    resources :users
      invoke  jbuilder_scaffold_controller
      create    app/controllers/users_controller.rb
      invoke    erb
      create      app/views/users
      create      app/views/users/index.html.erb
      create      app/views/users/edit.html.erb
      create      app/views/users/show.html.erb
      create      app/views/users/new.html.erb
      create      app/views/users/_form.html.erb
      invoke    test_unit
      create      test/controllers/users_controller_test.rb
      invoke    helper
      create      app/helpers/users_helper.rb
      invoke      test_unit
      create        test/helpers/users_helper_test.rb
      invoke    jbuilder
       exist      app/views/users
      create      app/views/users/index.json.jbuilder
      create      app/views/users/show.json.jbuilder
      invoke  assets
      invoke    coffee
      create      app/assets/javascripts/users.js.coffee
      invoke    scss
      create      app/assets/stylesheets/users.css.scss
      invoke  scss
      create    app/assets/stylesheets/scaffolds.css.scss

Добавив name:string и email:string, мы добились того, что модель User приобрела форму соответствующую Рис. 2.2. (Отметьте, что нет надобности включать параметр для id; он создается Rails автоматически для использования в качестве primary key в базе данных.)

Чтобы продолжить с демонстрационным приложением, мы сначала должны migrate (мигрировать, переместить) базу данных, используя Rake (Блок 2.1):

$ bundle exec rake db:migrate
==  CreateUsers: migrating ====================================================
-- create_table(:users)
   -> 0.0017s
==  CreateUsers: migrated (0.0018s) ===========================================

Это просто обновляет базу данных с нашей новой моделью данных users. (Мы узнаем больше о миграциях баз данных в Разделе 6.1.1.) Отметьте, что для того, чтобы обеспечить использование версии Rake, соответствующей нашему Gemfile, нам необходимо запустить rake используя bundle exec. (Если вы, в соответствии с рекомендациями в Разделе 1.2.2.3, используете RVM, вы можете опускать bundle exec. Для того чтобы узнать об альтернативных способах избавления от bundle exec, см. Section 3.6.1.)

Теперь мы можем запустить локальный веб-сервер, используя rails s, что является сокращением для rails server:

$ rails s

При этом демонстрационное приложение уже должно быть готово по адресу http://localhost:3000/.

2.2.1 Обзор пользователя

При посещении корневого url http://localhost:3000/ мы видим ту же самую дефолтную страницу Rails, что и на Рис. 1.3, но при генерировании ресурса Users scaffolding-ом мы также создали большое количество страниц для управления пользователями. Например, страницу для отображения списка всех пользователей на /users и страницу для создания нового пользователя на /users/new. Остальная часть этого раздела посвящена ураганному туру по этим страницам. В процессе этого тура для вас может оказаться полезным иногда поглядывать на Таблицу 2.1, которая показывает соответствие между страницами и их URL.

URLДействиеНазначение
/usersindexстраница, для отображения списка всех пользователей
/users/1showстраница показывающая пользователя с id 1
/users/newnewстраница для создания нового пользователя
/users/1/editeditстраница для редактирования пользователя с id 1
Таблица 2.1: Cоответствие между страницами и URL для ресурса Users.

Мы начнем со страницы показывающей всех пользователей в нашем приложении, называемой index; как вы могли бы ожидать, изначально там нет никаких пользователей (Рис. 2.4).

demo_blank_user_index_rails_3
Рис. 2.4: Начальная index страница для ресурса Users (/users). (полный размер)

Для того, чтобы создать нового пользователя мы посещаем new страницу, как показано на Рис. 2.5. (Поскольку http://localhost:3000 часть адреса явно будет повторятся до тех пор пока мы разрабатываем локально, я буду обычно опускать ее с этого момента.) В Главе 7 это станет страницей регистрации пользователя.

demo_new_user_rails_3
Рис. 2.5: Страница создания нового пользователя (/users/new). (полный размер)

Мы можем создать пользователя, введя значения имени и адреса электронной почты в текстовые поля и нажав затем кнопку Create User. Результат - страница show как видно на Рис. 2.6. (Зеленое приглашающее сообщение выполняется с использованием флэш, о котором мы узнаем в Разделе 7.4.2.) Отметим, что в URL /users/1; как вы могли бы подозревать, цифра 1 это просто атрибут id пользователя из Рис. 2.2. В Разделе 7.1эта страница станет профилем пользователя.

demo_show_user_rails_3
Рис. 2.6: Страница показывающая пользователя (/users/1). (полный размер)

Для того, чтобы изменить информацию пользователя, мы посещаем страницу edit (Рис. 2.7). Изменяя информацию о пользователе и нажимая кнопку Update User, мы изменяем информацию о пользователе в демонстрационном приложении (Рис. 2.8). (Как мы увидим в Главе 6, эти данные пользователя хранятся в бэкэнде базы данных.) Мы добавим функции edit/update (редактировать/обновить) пользователя к примеру приложения в Разделе 9.1.

demo_edit_user_rails_3
Рис. 2.7: Страница редактирования пользователя (/users/1/edit). (полный размер)
demo_update_user_rails_3
Рис. 2.8: Пользователь с обновленной информацией. (полный размер)

Теперь мы создадим второго пользователя, повторно посетив new страницу и предоставив второй набор информации о пользователе; получившаяся страница index показана на Рис. 2.9. Раздел 7.1 преобразует список пользователей в более отполированную страницу для демонстрации всех пользователей.

demo_user_index_two_rails_3
Рис. 2.9: Страница-список пользователей (/users) с вторым пользователем. (полный размер)

Показав как создавать, отображать и редактировать пользователей, мы переходим, наконец, к их удалению (Рис. 2.10). Следует проверить, что клик по ссылке показанной на Рис. 2.10 уничтожает второго пользователя, приводя к index странице с одним пользователем. (Если это не работает, убедитесь, что JavaScript включен в вашем браузере; Rails использует JavaScript, чтобы выдать запрос, который должен уничтожить пользователя.) Раздел 9.4 добавляет удаление пользователя к демонстрационному приложению, заботясь об ограничении его использования специальным классом административных пользователей.

demo_destroy_user_rails_3
Рис. 2.10: Уничтожение пользователя. (полный размер)

2.2.2 MVC в действии

Теперь, когда мы завершили быстрый обзор ресурса Пользователи (Users), давайте исследуем одну его определенную часть в контексте паттерна Модель-Представление-Контроллер (MVC) частично представленного в Разделе 1.2.6. Наша стратегия будет состоять в том, чтобы описать результаты типичного запроса браузера: посещение index страницы пользователя на /users—в терминах MVC (Рис. 2.11).

mvc_detailed
Рис. 2.11: Подробная схема MVC в Rails. (полный размер)
  1. Браузер выдает запрос на URL /users.
  2. Rails направляет /users к index действию в контроллере Users.
  3. Index действие просит, чтобы модель User получила всех пользователей (User.all).
  4. Модель User вытягивает всех пользователей из базы данных.
  5. Модель User возвращает список пользователей в контроллер.
  6. Контроллер получает пользователей в @users переменной, которую он передает index представлению.
  7. Представление использует Embedded (Встроенный) Ruby, чтобы визуализировать страницу как HTML.
  8. Контроллер возвращает HTML в браузер.3

Мы начинаем с запроса, выданного браузером — то есть, с результата ввода URL в адресной строке или клика по ссылке (Шаг 1 в Рис. 2.11). Этот запрос вызывает Rails маршрутизатор (Шаг 2), который отправляет к надлежащему действию контроллера, основываясь на URL (и, как мы увидим в Блоке 3.3, на типе запроса). Код, создающий перенаправление URL пользователя к действиям контроллера для ресурса Users представлен в Листинге 2.2; этот код фактически устанавливает таблицу пар URL/Действие, которые мы видели в Таблице 2.1. (Странная нотация :users это symbol, о котором мы узнаем в Разделе 4.3.3.)

Листинг 2.2. Маршруты Rails, с правилом для ресурса Users.
config/routes.rb
DemoApp::Application.routes.draw do
  resources :users
  .
  .
  .
end

Страницы из Раздела 2.2.1 соответствуют действиям в контроллере Users, который является набором связанных действий; контроллер, сгенерированный scaffolding, схематично показан в Листинге 2.3. Отметьте запись class UsersController < ApplicationController; это пример Ruby класса с наследованием. (Мы вкратце обсудим наследование в Разделе 2.3.4 и раскроем обе темы более подробно в Разделе 4.4.)

Листинг 2.3. Контроллер Users в схематичной форме.
app/controllers/users_controller.rb
class UsersController < ApplicationController
.
.
.

  def index
    .
    .
    .
  end

  def show
    .
    .
    .
  end

  def new
    .
    .
    .
  end

  def create
    .
    .
    .
  end

  def edit
    .
    .
    .
  end

  def update
    .
    .
    .
  end

  def destroy
    .
    .
    .
  end
end

Вы могли заметить, что действий больше чем страниц; index, show, new, и edit действия - все они соответствуют страницам из Раздела 2.2.1, но есть также дополнительные create (создать), update (обновить), и destroy (разрушить) действия. Эти действия обычно не визуализируют страниц (хотя иногда могут); вместо этого, их основная цель состоит в том, чтобы изменять информацию о пользователях в базе данных. Этот полный комплект действий контроллера, сведенный в Таблицу 2.2, представляет реализацию архитектуры REST в Rails (Блок 2.2), которая опирается на идеи передачи состояния представления идентифицированные и названые ученым Roy Fielding.4 Отметьте в Таблице 2.2 что есть некоторое наложение в URLs; например, и show и update действиям соответствует URL /users/1. Различие между ними в методе запроса HTTP на который они отвечают. Мы узнаем больше о методах запроса HTTP в Разделе 3.2.1.

HTTP запросURLДействиеНазначение
GET/usersindexстраница со списком всех пользователей
GET/users/1showстраница показывающая пользователя с id 1
GET/users/newnewстраница для создания нового пользователя
POST/userscreateсоздание нового пользователя
GET/users/1/editeditстраница для редактирования пользователя с id 1
PATCH/users/1updateобновление пользователя с id 1
DELETE/users/1destroyудаление пользователя с id 1
Таблица 2.2: RESTful маршруты предоставленные ресурсом Users в Листинге 2.2.

Чтобы исследовать отношения между контроллером Users и моделью User, давайте сосредоточимся на упрощенной версии index действия, показанной в Листинге 2.4. (Код scaffold уродливый и запутанный, так что я опустил большую его часть.)

Листинг 2.4. Упрощенное index действие для демонстрационного приложения.
app/controllers/users_controller.rb
class UsersController < ApplicationController
.
.
.

  def index
    @users = User.all
  end
  .
  .
  .
end

У этого index действия есть строка @users = User.all (Шаг 3), которая просит, чтобы модель User получила список всех пользователей из базы данных (Шаг 4), и затем помещает их в переменную @users (произносится “at-users”) (Шаг 5). Сама модель User появляется в Листинге 2.5; хотя она довольно проста, к ней прилагается большое количество функций из-за наследования (Раздел 2.3.4 и Раздел 4.4). В частности, за счет использования Rails библиотеки Active Record, код в Листинге 2.5 заставляет User.all возвратить всех пользователей.

Листинг 2.5. Модель User для демонстрационного приложения.
app/models/user.rb
class User < ActiveRecord::Base
end

Как только @users переменная определена, контроллер вызывает представление (Шаг 6), показанное в Листинге 2.6. Переменные, которые начинаются со знака @, называемые переменными экземпляра, автоматически доступны в представлении; в данном случае, представление index.html.erb в Листинге 2.6 перебирает список @users и выводит строку HTML для каждого. (Помните, вы не должны пытаться понять этот код прямо сейчас. Он показан только для иллюстрации.)

Листинг 2.6. Представление для index.
app/views/users/index.html.erb
<h1>Listing users</h1>

<table>
  <tr>
    <th>Name</th>
    <th>Email</th>
    <th></th>
    <th></th>
    <th></th>
  </tr>

<% @users.each do |user| %>
  <tr>
    <td><%= user.name %></td>
    <td><%= user.email %></td>
    <td><%= link_to 'Show', user %></td>
    <td><%= link_to 'Edit', edit_user_path(user) %></td>
    <td><%= link_to 'Destroy', user, method: :delete,
                                     data: { confirm: 'Are you sure?' } %></td>
  </tr>
<% end %>
</table>

<br />

<%= link_to 'New User', new_user_path %>

Представление преобразует свое содержимое в HТML (Шаг 7), который затем возвращается контроллером в браузер для отображения (Шаг 8).

2.2.3 Недостатки данного Users ресурса

Несмотря на полезность для общего обзора Rails, scaffold-ный ресурс Users имеет много серьезных недостатков.

  • Нет валидации данных. Наша модель User безропотно принимает такие данные как пустые имена и недопустимые адреса электронной почты.
  • Нет аутентификации. У нас нет понятия регистрации, и нет способа воспрепятствовать тому, чтобы любой пользователь выполнил любую операцию.
  • Нет тестов. Что, технически, не вполне верно — scaffolding включает рудиментарные тесты — но сгенерированные тесты уродливы и негибки, и они не тестируют на подтверждение правильности данных, аутентификацию, или какие нибудь другие пользовательские потребности.
  • Нет макета. Нет сколь-нибудь связанного стиля сайта или навигации.
  • Нет реального понимания. Если вы понимаете код scaffold-а, вам, вероятно, не стОит читать эту книгу.

2.3 Ресурс Microposts

Сгенерировав и исследовав ресурс Users, мы поворачиваемся теперь к связанному с ним ресурсу Microposts. На протяжении этого раздела я рекомендую сравнивать элементы ресурса Microposts с аналогичными элементами User из Раздела 2.2; вы должны увидеть, что эти два ресурса во многом параллельны друг другу. RESTful структура Rails приложений лучше всего усваивается посредством наблюдения за подобными повторяющимися формами; действительно, наблюдение параллельной структуры Users и Microposts даже на этой ранней стадии является одной из причин написания этой главы. (Как мы увидим, написание приложения, более устойчивого, нежели игрушечный пример в этой главе, требует значительных усилий — мы не увидим ресурс Microposts до Главы 10 — и я не хотел так надолго откладывать его первое появление.)

2.3.1 Микрообзор микросообщений

Как и с ресурсом Users, мы генерируем код scaffold для ресурса Microposts, используя rails generate scaffold, в этом случае реализуя модель данных из Рис. 2.3:5

$ rails generate scaffold Micropost content:string user_id:integer
      invoke  active_record
      create    db/migrate/20130307005528_create_microposts.rb
      create    app/models/micropost.rb
      invoke    test_unit
      create      test/models/micropost_test.rb
      create      test/fixtures/microposts.yml
      invoke  resource_route
       route    resources :microposts
      invoke  jbuilder_scaffold_controller
      create    app/controllers/microposts_controller.rb
      invoke    erb
      create      app/views/microposts
      create      app/views/microposts/index.html.erb
      create      app/views/microposts/edit.html.erb
      create      app/views/microposts/show.html.erb
      create      app/views/microposts/new.html.erb
      create      app/views/microposts/_form.html.erb
      invoke    test_unit
      create      test/controllers/microposts_controller_test.rb
      invoke    helper
      create      app/helpers/microposts_helper.rb
      invoke      test_unit
      create        test/helpers/microposts_helper_test.rb
      invoke    jbuilder
       exist      app/views/microposts
      create      app/views/microposts/index.json.jbuilder
      create      app/views/microposts/show.json.jbuilder
      invoke  assets
      invoke    coffee
      create      app/assets/javascripts/microposts.js.coffee
      invoke    scss
      create      app/assets/stylesheets/microposts.css.scss
      invoke  scss
   identical    app/assets/stylesheets/scaffolds.css.scss

Чтобы обновить нашу базу данных с новой моделью данных, мы должны запустить миграцию как в Разделе 2.2:

$ bundle exec rake db:migrate
==  CreateMicroposts: migrating ===============================================
-- create_table(:microposts)
   -> 0.0023s
==  CreateMicroposts: migrated (0.0026s) ======================================

Теперь мы имеем возможность создавать микропосты тем же образом, каким мы создавали пользователей в Разделе 2.2.1. Как вы могли бы предположить, генератор scaffold добавил в файл маршрутов Rails правило для ресурса Microposts, как видно в Листинге 2.7.6 Как и с users, resources :microposts маршрутное правило направляет URL микросообщений на действия в контроллере Microposts, как видно в Таблице 2.3.

Листинг 2.7. Маршруты Rails с новым правилом для ресурсов Microposts.
config/routes.rb
DemoApp::Application.routes.draw do
  resources :microposts
  resources :users
  .
  .
  .
end
HTTP запросURLДействиеНазначение
GET/micropostsindexстраница со списком всех микросообщений
GET/microposts/1showстраница показывающая микросообщение с id 1
GET/microposts/newnewстраница для создания нового микросообщения
POST/micropostscreateсоздание нового микросообщения
GET/microposts/1/editeditстраница для редактирования микросообщения с id 1
PATCH/microposts/1updateобновление микросообщения с id 1
DELETE/microposts/1destroyудаление микросообщения с id 1
Таблица 2.3: RESTful маршруты, обеспеченные ресурсом Microposts в Листинге 2.7.

Сам Microposts контроллер в схематичной форме представлен в Листинге 2.8. Отметьте, что, кроме наличия MicropostsController вместо UsersController, Листинг 2.8 идентичен коду в Листинге 2.3. Это отражение REST архитектуры, характерной для обоих ресурсов.

Листинг 2.8. Контроллер Microposts в схематичной форме.
app/controllers/microposts_controller.rb
class MicropostsController < ApplicationController
.
.
.

  def index
    .
    .
    .
  end

  def show
    .
    .
    .
  end

  def new
    .
    .
    .
  end

  def create
    .
    .
    .
  end

  def edit
    .
    .
    .
  end

  def update
    .
    .
    .
  end

  def destroy
    .
    .
    .
  end
end

для того чтобы сделать несколько настоящих микросообщений, мы вводим информацию на new странице микросообщений, /microposts/new как видно на Рис. 2.12.

demo_new_micropost_rails_3
Рис. 2.12: Страница для создания микросообщений (/microposts/new). (полный размер)

Теперь создайте одно - два микросообщения, удостоверьтесь, чтобы по крайней мере у одного из них был user_id = 1 для сопоставления с id первого пользователя, созданного в Разделе 2.2.1. Результат должен быть похож на Рис. 2.13.

demo_micropost_index_rails_3
Рис. 2.13: Страница списка микросообщений (/microposts). (полный размер)

2.3.2 Помещение микро в микросообщения

Каждое микросообщение, достойное своего имени, должно иметь некоторые средства предписания длины сообщения. Реализация этого ограничения в Rails легка с проверками допустимости (валидациями); чтобы принять микросообещния длиной не более 140 символов (а-ля Twitter), мы используем проверку допустимости (валидацию) длины. В этой точке следует открыть файл app/models/micropost.rb в вашем текстовом редакторе или IDE и заполнить его содержимым Листинга 2.9. (Использование валидации из Листинга 2.9 характерно для Rails 3; если вы ранее работали с Rails 2.3, следует сравнить это с использованием validates_length_of.)

Листинг 2.9. Ограничение микросообщений максимумом в 140 знаков посредством валидации длины.
app/models/micropost.rb
class Micropost < ActiveRecord::Base
  validates :content, length: { maximum: 140 }
end

Код в Листинге 2.9 может выглядеть довольно таинственно — мы рассмотрим валидацию более тщательно в Разделе 6.2 — но его эффект станет вполне очевиден, если мы перейдем в новую страницу микросообщений и введем больше чем 140 символов для контента сообщения. Как видно на Рис. 2.14, Rails выдает сообщение об ошибке указывающее на то, что контент микросообщения является слишком длинным. (Мы узнаем больше о сообщениях об ошибках в Разделе 7.3.3.)

micropost_length_error_rails_3
Рис. 2.14: Сообщение об ошибке для неудачно созданного микросообщения. (полный размер)

2.3.3 A user has_many microposts (Пользователь имеет_много микросообщений)

Одна из наиболее мощных функций Rails – возможность формировать связи между различными моделями данных. В случае нашей модели User у каждого пользователя потенциально есть много микросообщений. Мы можем выразить это в коде, обновив модели User и Micropost как это показано в Листинге 2.10 и Листинге 2.11.

Листинг 2.10. У пользователя есть много микросообщений (user has many microposts).
app/models/user.rb
class User < ActiveRecord::Base
  has_many :microposts
end
Листинг 2.11. Микросообщения принадлежат пользователю (micropost belongs to a user).
app/models/micropost.rb
class Micropost < ActiveRecord::Base
  belongs_to :user
  validates :content, length: { maximum: 140 }
end

Мы можем увидеть результат применения этой ассоциации на Рис. 2.15. Из-за user_id столбца в таблице microposts Rails (используя Active Record) может вывести микросообщения, связанные с каждым пользователем.

micropost_user_association
Рис. 2.15: Связь между микросообщениями и пользователями.

В Главе 10 и Главе 11, мы будем использовать ассоциацию пользователей и микросообщений и чтобы вывести на экран все микросообщения пользователя, и чтобы создать Twitter-подобную подачу микросообщений. Пока, мы можем исследовать применение связи микросообщения-пользователь с помощью консоли, которая является полезным инструментом для взаимодействия с Rails приложениями. Сначала мы вызовем консоль командой rails console в командной строке, а затем получим первого пользователя из базы данных, используя User.first (поместив результаты в переменную first_user):7

$ rails console
>> first_user = User.first
=> #<User id: 1, name: "Michael Hartl", email: "michael@example.org",
created_at: "2013-03-06 02:01:31", updated_at: "2013-03-06 02:01:31">
>> first_user.microposts
=> [#<Micropost id: 1, content: "First micropost!", user_id: 1, created_at:
"2013-03-06 02:37:37", updated_at: "2013-03-06 02:37:37">, #<Micropost id: 2,
content: "Second micropost", user_id: 1, created_at: "2013-03-06 02:38:54",
updated_at: "2013-03-06 02:38:54">]
>> exit

(Я включил последнюю строку только чтобы продемонстрировать, как выйти из консоли, и на большинстве систем вы можете использовать Ctrl-d с этой же целью.) Здесь мы получили доступ к микросообщениям пользователя, используя код first_user.microposts: с этим кодом Active Record автоматически возвращает все микросообщения с user_id равным id first_user (в данном случае, 1). Мы узнаем намного больше о возможностях ассоциаций (связей) Active Record в Главе 10 и Главе 11.

2.3.4 Иерархия наследования

Мы закончим наше обсуждение демонстрационного приложения кратким описанием иерархии классов контроллеров и моделей в Rails. Это обсуждение будет иметь много смысла, только если у вас был некоторый опыт объектно-ориентированного программирования (ООП); если вы не изучали ООП, не стесняйтесь пропустить этот раздел. В частности, если вы не знакомы с классами (обсуждаемыми в Разделе 4.4), я предлагаю вернуться к этому разделу позже.

Мы начнем со структуры наследования для моделей. Сравнивая Листинг 2.12 с Листингом 2.13, мы видим, что и модель User и модель Micropost наследовались (через левую угловую скобку <) от ActiveRecord::Base, который является базовым классом для моделей, предоставляемых библиотекой ActiveRecord; схема, резюмирующая это отношение, представлена на Рис. 2.16. Благодаря наследованию от ActiveRecord::Base наши объекты модели получают возможность связываться с базой данных, обрабатывать столбцы базы данных как Ruby атрибуты и так далее.

Листинг 2.12. Класс User, с наследованием.
app/models/user.rb
class User < ActiveRecord::Base
  .
  .
  .
end
Листинг 2.13. Класс Micropost с наследованием.
app/models/micropost.rb
class Micropost < ActiveRecord::Base
  .
  .
  .
end
demo_model_inheritance
Рис. 2.16: Иерархия наследования для моделей User и Micropost.

Структура наследования для контроллеров лишь немногим более сложная. Сравнивая Листинг 2.14 с Листингом 2.15, мы видим, что и контроллер User и контроллер Micropost наследовались от Application controller. Исследуя Листинг 2.16, мы видим, что сам ApplicationController наследует от ActionController::Base; это базовый класс для контроллеров, обеспеченных Rails библиотекой Action Pack. Отношения между этими классами иллюстрируются в Рис. 2.17.

Листинг 2.14. Класс UsersController, с наследованием.
app/controllers/users_controller.rb
class UsersController < ApplicationController
  .
  .
  .
end
Листинг 2.15. Класс MicropostsController, с наследованием.
app/controllers/microposts_controller.rb
class MicropostsController < ApplicationController
  .
  .
  .
end
Листинг 2.16. Класс ApplicationController, с наследованием.
app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
  .
  .
  .
end
demo_controller_inheritance
Рис. 2.17: Иерархия наследования для контроллеров Users и Microposts.

Как и с наследованием моделей, будучи, в конечном счете, наследниками ActionController::Base и Users и Microposts контроллеры имеют большое количество функций, таких как возможность управлять объектами модели, фильтровать входящие запросы HTTP, и визуализировать представления как HTML. Так как все контроллеры Rails наследовались от ApplicationController, правила, определенные в ApplicationController автоматически, применяются к каждому действию в приложении. Например, в Разделе 8.2.1 мы увидим как включить хелперы для входа и выхода во все контроллеры примера приложения.

2.3.5 Развертывание демонстационного приложения

Закончив ресурс Microposts, мы можем отправить репозиторий на GitHub:

$ git add .
$ git commit -a -m "Finish demo app"
$ git push

Обычно вам следует делать более частые коммиты, но для этой главы единственный большой коммит в конце - это вполне нормально.

Можно также развернуть demo app на Heroku как и в Разделе 1.4:

$ heroku create
$ git push heroku master

(Как было отмечено в Разделе 1.4.1, некоторые читатели сообщали о необходимости прекомпиляции ассетов при помощи команды:

# Это должно быть использовано только если вы не можете задеплоить на Heroku.
$ rake assets:precompile
$ git add .
$ git commit -m "Add precompiled assets for Heroku"
$ git push heroku master

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

Также необходимо запустить миграции продакшен базы данных:

$ heroku run rake db:migrate

Это обновит базу данных на Heroku с необходимой моделью данных.

2.4 Заключение

Мы подошли к концу 9 144 метрового (30,000-foot ) обзора Rails приложения. У demo app, разработанного в этой главе, есть несколько достоинств и масса недостатков.

Достоинства

  • Общее представление о Rails
  • Введение в MVC
  • Первый вкус архитектуры REST
  • Начальное моделирование данных
  • Живое, поддерживаемое базой данных веб-приложение в production

Недостатки

  • Нет собственного макета или стиля
  • Нет статических страниц (таких как "Главная" или "О нас")
  • Нет паролей пользователя
  • Нет изображений пользователя
  • Нет регистрации
  • Нет безопасности
  • Нет автоматической связи пользователь/микросообщение
  • Нет понятий “following” или “followed”
  • Нет потока (ленты) микросообщений
  • Нет разработки через тестирование
  • Нет реального понимания

Остальная часть этого учебника посвящена усилению достоинств и устранению недостатков.

  1. Моделируя более длинные сообщения, для нормального (не микро) блога, следует использовать тип text вместо string
  2. Имя scaffold следует за соглашением в соответствии с которым, модели имеют единственное число, в отличие от ресурсов и контроллеров, которые используются во множественном числе. Таким образом, у нас есть User вместо Users
  3. Некоторые источники утверждают, что представление возвращает HTML непосредственно браузеру (через веб-сервер, такой как Apache или Nginx). Независимо от деталей реализации, я предпочитаю думать о контроллере как о центральном хабе через который проходят информационные потоки всего приложения. 
  4. Fielding, Roy Thomas. Architectural Styles and the Design of Network-based Software Architectures. Doctoral dissertation, University of California, Irvine, 2000. 
  5. Как и с User scaffold, генератор scaffold для микросообщений следует сингулярному соглашению для моделей Rails; таким образом, мы имеем, generate Micropost, а не generate MicropostS
  6. У кода scaffold могут быть дополнительные новые строки по сравнению с Листингом 2.7. Это не повод для беспокойства, поскольку Ruby игнорирует дополнительные новые строки. 
  7. Ваше приглашение командной строки, вероятно, будет чем-то вроде ruby-2.0.0-head >, но я буду использовать >> поскольку версии Ruby могут отличаться.