В этой главе мы разработаем простое демонстрационное приложение, чтобы показать мощь Rails. Цель - получить общее представление о программировании на Ruby on Rails (и веб-разработке в целом), быстро сгенерировав приложение, используя scaffold generators. Как обсуждалось в Блоке 1.2, остальная часть книги будет применять противоположный подход, постепенно разрабатывая приложение с объяснением всех новых понятий по мере их появления, но для быстрого обзора (и некоторого быстрорастворимого удовлетворения) нет ничего лучше чем scaffolding. Конечное демонстрационное приложение позволит нам взаимодействовать с ним через свои URL, дав нам понимание структуры Rails приложений, включая первый пример REST архитектуры предпочитаемой Rails.
Как и предстоящий пример приложения, демонстрационное приложение будет состоять из пользователей и связанных с ними микросообщений (образуя минималистичное приложение в стиле Twitter). Функциональность будет совершенно слаборазвита и многие из шагов будут походить на волшебство, но не переживайте: полный пример приложения разработает подобное же приложение с нуля, начиная с Главы 3, и я дам многочисленные ссылки на более поздний материал. Тем временем, имейте терпение и немного веры - все таки основная цель данного учебника - удержать вас вне этого поверхностного, управляемого scaffold подхода, для достижения более глубокого понимания Rails.
В этом Разделе мы обрисуем в общих чертах наши планы относительно демонстрационного приложения. Как и в Разделе 1.2.3, мы начнем с создания скелета приложения, используя команду rails:
$ cd ~/rails_projects $ rails new demo_app $ cd demo_app
Затем, мы используем текстовый редактор, чтобы обновить Gemfile необходимый Bundler, содержанием из Листинга 2.1.
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"
(рис 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 будет уникальный целочисленный идентификатор называемый id, публично видимое имя (тип .
(рис 2.2) Модель данных для пользователей.
Как мы увидим в Разделе 6.1.1, табличка соответствует таблице в базе данных и id, name, и email атрибуты это столбцы этой таблицы
Ядро модели данных микросообщений даже проще чем для пользователей: микросообщение имеет только id и поле content для текста микросообщения (тип -
(рис 2.3) Модель данных для микросообщений.
Мы увидим в Разделе 2.3.3 (и более полно в Главе 10) как этот user_id атрибут позволит нам кратко реализовать идею, что у пользователя потенциально есть много связанных с ним микросообщений.
В этом разделе мы реализуем модель данных пользователей из Раздела 2.1.1, наряду с веб-интерфейсом к этой модели. Эта комбинация образует ресурс Users, который позволит нам думать о пользователях как об объектах, которые могут быть созданы, считаны, обновлены, и удалены через сеть с использованием HTTP протокола. Как обещалось во введении, наш ресурс Users будет создаваться программой scaffold generator, которая стандартно поставляется с каждым проектом Rails. Я настоятельно прошу вас не всматриваться в генерируемый код; на этом этапе он лишь запутает вас.
Rails scaffolding запускается передачей
$ 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
Добавив (Отметьте, что нет надобности включать параметр для id; он создается Rails автоматически для использования в качестве primary key в базе данных.)
$ 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.1.Rake
В традиции Unix, make утилита играет важную роль в сборке исполняемых программ из исходного кода; множество компьютерных хакеров зафиксировали в мышечной памяти строку
$ ./configure make sudo make install
обычно используемую, для компиляции кода на Unix системах (включая Linux и Mac OS X).
Rake это Ruby make, make-подобный язык написанный на Ruby. Rails использует Rake, в значительной степени, специально для неисчислимых небольших административных задач, необходимых при разработке поддерживаемых базой данных веб-приложений. rake db:migrate команда, вероятно, наиболее распространена, но есть и многие другие; можно увидеть список задач базы данных, используя -T db:
$ bundle exec rake -T db
Чтобы увидеть все доступные Rake задачи, запустите
$ bundle exec rake -T
Список, вероятно, будет подавляющим, но не волнуйтесь, вы не должны знать все (или даже большую часть) этих команд. К концу Учебника Rails, вы будете знать все самые важные
При посещении корневого url http://localhost:3000/ мы видим ту же самую дефолтную страницу Rails, что и на рис 1.3, но при генерировании ресурса Users scaffolding-ом мы также создали большое количество страниц для управления пользователями. Например, страницу для отображения списка всех пользователей на http://localhost:3000/users, которая показывает соответствие между страницами и их URL.
| URL | Действие | Назначение |
|---|---|---|
| /users | index | страница, для отображения списка всех пользователей |
| /users/1 | show | страница показывающая пользователя с id |
| /users/new | new | страница для создания нового пользователя |
| /users/1/edit | edit | страница для редактирования пользователя с id |
Мы начнем со страницы показывающей всех пользователей в нашем приложении, называемой ).
(рис 2.4) Начальная index страница для ресурса Users (/users).
Для того, чтобы создать нового пользователя мы посещаем new страницу, как показано на рис 2.5 (Поскольку http://localhost:3000 часть адреса явно будет повторятся до тех пор пока мы разрабатываем локально, я буду обычно опускать ее с этого момента.) В Главе 7 это станет страницей регистрации пользователя.
(рис 2.5) Страница создания нового пользователя (/users/new)
Мы можем создать пользователя, введя значения имени и адреса электронной почты в текстовые поля и нажав затем кнопку Create User. Результат - страница show как видно на рис 2.6 (Зеленое приглашающее сообщение выполняется с использованием флэш, о котором мы узнаем в Разделе 7.4.2.) Отметим, что в URL /users/1; как вы могли бы подозревать, цифра В Разделе 7.1 эта страница станет профилем пользователя.
(рис 2.6) Страница показывающая пользователя (/users/1).
Для того, чтобы изменить информацию пользователя, мы посещаем страницу ). Изменяя информацию о пользователе и нажимая кнопку Update User, мы изменяем информацию о пользователе в демонстрационном приложении (рис 2.8). (Как мы увидим в Главе 6, эти данные пользователя хранятся в бэкэнде базы данных.) Мы добавим функции edit/update (редактировать/обновить) пользователя к примеру приложения в Разделе 9.1.
(рис 2.7) Страница редактирования пользователя (/users/1/edit).
(рис 2.8) Пользователь с обновленной информацией.
Теперь мы создадим второго пользователя, повторно посетив new страницу и предоставив второй набор информации о пользователе; получившаяся страница index показана на рис 2.9. Раздел 7.1 преобразует список пользователей в более отполированную страницу для демонстрации всех пользователей.
(рис 2.9) Страница-список пользователей (/users) с вторым пользователем.
Показав как создавать, отображать и редактировать пользователей, мы переходим, наконец, к их удалению (рис 2.10). Следует проверить, что клик по ссылке показанной на рис 2.10 уничтожает второго пользователя, приводя к index странице с одним пользователем. (Если это не работает, убедитесь, что JavaScript включен в вашем браузере; Rails использует JavaScript, чтобы выдать запрос, который должен уничтожить пользователя.) Раздел 9.4 добавляет удаление пользователя к демонстрационному приложению, заботясь об ограничении его использования специальным классом административных пользователей.
(рис 2.10) Уничтожение пользователя.
Теперь, когда мы завершили быстрый обзор ресурса Пользователи (Users), давайте исследуем одну его определенную часть в контексте паттерна Модель-Представление-Контроллер (MVC) частично представленного в Разделе 1.2.6. Наша стратегия будет состоять в том, чтобы описать результаты типичного запроса браузера: посещение index страницы пользователя на /users—в терминах MVC (рис 2.11).
(рис 2.11) Подробная схема MVC в Rails.
Мы начинаем с запроса, выданного браузером — то есть, с результата ввода URL в адресной строке или клика по ссылке (Шаг 1 в рис 2.11). Этот запрос вызывает Rails маршрутизатор (Шаг 2), который отправляет к надлежащему действию контроллера, основываясь на URL (и, как мы увидим в Блоке 3.3, на типе запроса). Код, создающий перенаправление URL пользователя к действиям контроллера для ресурса Users представлен в Листинге 2.2; этот код фактически устанавливает таблицу пар URL/Действие, которые мы видели в Таблице 2.1. (Странная нотация :users это symbol, о котором мы узнаем в Разделе 4.3.3.)
Страницы из Раздела 2.2.1 соответствуют действиям в контроллере Users, который является набором связанных действий; контроллер, сгенерированный scaffolding, схематично показан в Листинге 2.3. Отметьте запись class UsersController < ApplicationController; это пример Ruby класса с наследованием. (Мы вкратце обсудим наследование в Разделе 2.3.4 и раскроем обе темы более подробно в Разделе 4.4.)
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
Вы могли заметить, что действий больше чем страниц; , представляет реализацию архитектуры REST в Rails (Блок 2.2), которая опирается на идеи передачи состояния представления идентифицированные и названые ученым Roy Fielding.
| HTTP запрос | URL | Действие | Назначение |
|---|---|---|---|
| GET | /users | index | страница со списком всех пользователей |
| GET | /users/1 | show | страница показывающая пользователя с id 1 |
| GET | /users/new | new | страница для создания нового пользователя |
| POST | /users | create | создание нового пользователя |
| GET | /users/1/edit | edit | страница для редактирования пользователя с id 1 |
| PATCH | /users/1 | update | обновление пользователя с id 1 |
| DELETE | /users/1 | destroy | удаление пользователя с id 1 |
Блок 2.2.REpresentational State Transfer (REST, "передача состояния представления")
Если вы много читали о веб-разработке на Ruby on Rails, вы видели много ссылок на "REST", являющуюся акронимом для REpresentational State Transfer ("передача состояния представления"). REST - архитектурный стиль для разработки распределенных, сетевых систем и приложений, таких как World Wide Web и веб-приложения. Хотя теория REST довольно абстрактна, в контексте Rails приложений REST означает, что большинство компонентов приложения (таких как пользователи и микросообщения) моделируются как ресурсы, которые могут быть созданы (Сreated), прочитаны (Read), обновлены (Updated), и удалены (Deleted) - операции, которые соответствуют и операциям CRUD, реляционных баз данных и четырем фундаментальным методам запроса HTTP: POST, GET, PATCH, и DELETE. (Мы узнаем больше о запросах HTTP в Разделе 3.2.1 и особенно в Блоке 3.3.)
Как разработчику Rails приложений, RESTful стиль разработки помогает вам определиться какие контроллеры и действия писать: вы просто структурируете приложение, используя ресурсы, которые создаются, читаются, обновляются, и удаляются. В случае пользователей и микросообщений, этот процесс является простым, так как они - натуральные ресурсы по определению. В Главе 11 мы увидим пример, где принципы REST позволяют нам моделировать более тонкую проблему "Слежения за сообщениями пользователей" естественным и удобным способом.
Чтобы исследовать отношения между контроллером Users и моделью User, давайте сосредоточимся на упрощенной версии index действия, показанной в Листинге 2.4. (Код scaffold уродливый и запутанный, так что я опустил большую его часть.)
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 возвратить всех пользователей.
class User < ActiveRecord::Base end
Как только @users переменная определена, контроллер вызывает представление (Шаг 6), показанное в Листинге 2.6. Переменные, которые начинаются со знака @, называемые переменными экземпляра, автоматически доступны в представлении; в данном случае, представление index.html.erb в Листинге 2.6 перебирает список @users и выводит строку HTML для каждого. (Помните, вы не должны пытаться понять этот код прямо сейчас. Он показан только для иллюстрации.)
<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).
Несмотря на полезность для общего обзора Rails, scaffold-ный ресурс Users имеет много серьезных недостатков.
Сгенерировав и исследовав ресурс Users, мы поворачиваемся теперь к связанному с ним ресурсу Microposts. На протяжении этого раздела я рекомендую сравнивать элементы ресурса Microposts с аналогичными элементами User из Раздела 2.2; вы должны увидеть, что эти два ресурса во многом параллельны друг другу. RESTful структура Rails приложений лучше всего усваивается посредством наблюдения за подобными повторяющимися формами; действительно, наблюдение параллельной структуры Users и Microposts даже на этой ранней стадии является одной из причин написания этой главы. (Как мы увидим, написание приложения, более устойчивого, нежели игрушечный пример в этой главе, требует значительных усилий — мы не увидим ресурс Microposts до Главы 10 — и я не хотел так надолго откладывать его первое появление.)
Как и с ресурсом Users, мы генерируем код scaffold для ресурса Microposts, используя :generate Micropost, а не generate MicropostS.
$ 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.
DemoApp::Application.routes.draw do resources :microposts resources :users . . . end
| HTTP запрос | URL | Действие | Назначение |
|---|---|---|---|
| GET | /microposts | index | страница со списком всех микросообщений |
| GET | /microposts/1 | show | страница показывающая микросообщение с id 1 |
| GET | /microposts/new | new | страница для создания нового микросообщения |
| POST | /microposts | create | создание нового микросообщения |
| GET | /microposts/1/edit | edit | страница для редактирования микросообщения с id 1 |
| PATCH | /microposts/1 | update | обновление микросообщения с id 1 |
| DELETE | /microposts/1 | destroy | даление микросообщения с id 1 |
Сам Microposts контроллер в схематичной форме представлен в Листинге 2.8. Отметьте, что, кроме наличия MicropostsController вместо UsersController, Листинг 2.8 идентичен коду в Листинге 2.3.. Это отражение REST архитектуры, характерной для обоих ресурсов.
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 как видно на рис /microposts/new" type="url">/microposts/new как видно на (рис 2.12) Страница для создания микросообщений (/microposts/new).
Теперь создайте одно - два микросообщения, удостоверьтесь, чтобы по крайней мере у одного из них был .
(рис 2.13) Страница списка микросообщений (/microposts).
Каждое микросообщение, достойное своего имени, должно иметь некоторые средства предписания длины сообщения. Реализация этого ограничения в Rails легка с проверками допустимости (валидациями); чтобы принять микросообещния длиной не более 140 символов (а-ля Twitter), мы используем проверку допустимости (валидацию) длины. В этой точке следует открыть файл app/models/micropost.rb в вашем текстовом редакторе или IDE и заполнить его содержимым Листинга 2.9. (Использование валидации из Листинга 2.9 характерно для Rails 3; если вы ранее работали с Rails 2.3, следует сравнить это с использованием validates_length_of.)
class Micropost < ActiveRecord::Base
validates :content, length: { maximum: 140 }
end
Код в Листинге 2.9 может выглядеть довольно таинственно — мы рассмотрим валидацию более тщательно в Разделе 6.2 — но его эффект станет вполне очевиден, если мы перейдем в новую страницу микросообщений и введем больше чем 140 символов для контента сообщения. Как видно на рис 2.9" type="example">Листинге 2.9 может выглядеть довольно таинственно — мы рассмотрим валидацию более тщательно в Разделе 6.2 — но его эффект станет вполне очевиден, если мы перейдем в новую страницу микросообщений и введем больше чем 140 символов для контента сообщения. Как видно на (рис 2.14) Сообщение об ошибке для неудачно созданного микросообщения.
Одна из наиболее мощных функций Rails – возможность формировать связи между различными моделями данных. В случае нашей модели User у каждого пользователя потенциально есть много микросообщений. Мы можем выразить это в коде, обновив модели User и Micropost как это показано в Листинге 2.10 и Листинге 2.11.
class User < ActiveRecord::Base has_many :microposts end
class Micropost < ActiveRecord::Base
belongs_to :user
validates :content, length: { maximum: 140 }
end
Мы можем увидеть результат применения этой ассоциации на рис 2.15. Из-за user_id столбца в таблице microposts Rails (используя Active Record) может вывести микросообщения, связанные с каждым пользователем.
(рис 2.15) Связь между микросообщениями и пользователями.
В Главе 10 и Главе 11, мы будем использовать ассоциацию пользователей и микросообщений и чтобы вывести на экран все микросообщения пользователя, и чтобы создать Twitter-подобную подачу микросообщений. Пока, мы можем исследовать применение связи микросообщения-пользователь с помощью консоли, которая является полезным инструментом для взаимодействия с Rails приложениями. Сначала мы вызовем консоль командой ruby-2.0.0-head >, но я буду использовать >> поскольку версии Ruby могут отличаться
$ 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.
Мы закончим наше обсуждение демонстрационного приложения кратким описанием иерархии классов контроллеров и моделей в Rails. Это обсуждение будет иметь много смысла, только если у вас был некоторый опыт объектно-ориентированного программирования (ООП); если вы не изучали ООП, не стесняйтесь пропустить этот раздел. В частности, если вы не знакомы с классами (обсуждаемыми в Разделе 4.4), я предлагаю вернуться к этому разделу позже.
Мы начнем со структуры наследования для моделей. Сравнивая Листинг 2.12 с Листингом 2.13, мы видим, что и модель User и модель Micropost наследовались (через левую угловую скобку <) от . Благодаря наследованию от ActiveRecord::Base наши объекты модели получают возможность связываться с базой данных, обрабатывать столбцы базы данных как Ruby атрибуты и так далее.
class User < ActiveRecord::Base . . . end
class Micropost < ActiveRecord::Base . . . end
(рис 2.16) Иерархия наследования для моделей User и Micropost.
Структура наследования для контроллеров лишь немногим более сложная. Сравнивая Листинг 2.14 с Листингом 2.15, мы видим, что и контроллер User и контроллер Micropost наследовались от Application controller. Исследуя Листинг 2.16, мы видим, что сам .
class UsersController < ApplicationController . . . end
class MicropostsController < ApplicationController . . . end
class ApplicationController < ActionController::Base . . . end
(рис 2.17) Иерархия наследования для контроллеров Users и Microposts.
Как и с наследованием моделей, будучи, в конечном счете, наследниками ActionController::Base и Users и Microposts контроллеры имеют большое количество функций, таких как возможность управлять объектами модели, фильтровать входящие запросы HTTP, и визуализировать представления как HTML. Так как все контроллеры Rails наследовались от ApplicationController, правила, определенные в ApplicationController автоматически, применяются к каждому действию в приложении. Например, в Разделе 8.2.1 мы увидим как включить хелперы для входа и выхода во все контроллеры примера приложения.
Закончив ресурс 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 с необходимой моделью данных.
Мы подошли к концу 9 144 метрового (30,000-foot ) обзора Rails приложения. У demo app, разработанного в этой главе, есть несколько достоинств и масса недостатков.
Достоинства
Недостатки
Остальная часть этого учебника посвящена усилению достоинств и устранению недостатков.
Для получения официальных документов о завершении программы дополнительного профессионального образования (удостоверения о повышении квалификации, дипломов о профессиональной переподготовке и MBA) необходимо предоставить:
Внимание! Вы можете не заказывать доставку бумажной версии официального документы, а скачать его в электронном виде и распечатать самостоятельно. Информация о выданном документе в течение 1 месяца загружается в Федеральную информационную систему «Федеральный реестр сведений о документах об образовании и (или) о квалификации, документах об обучении» - ФИС ФРДО.
Доступ на новый сайт осуществляется с использованием адреса электронной почты, который был указан вами при регистрации на "старом". Мы постарались перенести все ваши данные с прежнего ресурса, однако не исключена вероятность потери части информации.
При возникновении проблемы со входом, воспользуйтесь функцией сброса пароля
Если вы обнаружите несоответствия, пожалуйста, сообщите нам.