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

Рисунок 2.11: Подробная схема MVC в Rails.
- Браузер выдает запрос на URL /users.
- Rails направляет /users к
index
действию в контроллере Users (Пользователи) -
Index
действие просит, чтобы модель User получила всех пользователей (User.all
). - Модель User получает по запросу всех пользователей из базы данных.
- Модель User возвращает список пользователей в контроллер.
- Контроллер получает пользователей в
@users
переменной, которую передаетindex
представлению. - Представление использует Embedded (Встроенный) Ruby, чтобы визуализировать страницу как HTML.
- Контроллер возвращает HTML в браузер 7
Мы начинаем с запроса, выданного браузером - то есть, с результата ввода URL в строке поиска или щелчка по ссылке (Шаг 1 в Рис. 2.11). Этот запрос вызывает Rails маршрутизатор (Шаг 2), который отправляет к надлежащему, действию контроллера, основываясь на URL (и, как мы увидим в Блоке 3.1, на типе запроса). Код создающий перенаправление URL пользователя к действиям контроллера для ресурса Users появится в Листинге 2.2;8 этот код фактически устанавливает таблицу пар URL/Действие, которые мы видели в Таблице 2.1.
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.)
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). Отметьте в Таблице 2.2, что есть некоторое наложение в URL; например, и user show
и update
действиям соответствует URL /users/1. Различие между ними в методе запроса HTTP на который они отвечают. Мы узнаем больше о методах запроса HTTP в Разделе 3.2.2.
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 |
PUT | /users/1 | update | обновление пользователя с id 1 |
DELETE | /users/1 | destroy | удаление пользователя с id 1 |
Если Вы много читали о веб-разработке Ruby on Rails, Вы видели много ссылок на “REST”, который является акронимом для (REpresentational State Transfer, «передача состояния представления»). REST - архитектурный стиль для разработки распределенных, сетевых систем и приложений, таких как World Wide Web и веб-приложения. Хотя теория REST довольно абстрактна, в контексте приложений Rails, REST означает, что большинство компонентов приложения (таких как пользователи и микросообщения) моделируется как ресурсы , которые могут быть созданы (Сreated), прочитаны (Read), обновленны (Updated), и удалены (Deleted) - операции, которые соответствуют и операциям CRUD, реляционных баз данных и четырем фундаментальным методам запроса HTTP: POST, GET, PUT, и DELETE. (Мы узнаем больше о запросах HTTP в Разделе 3.2.2, особенно в Блоке 3.1.)
Как разработчику приложений Rails, RESTful стиль разработки помогает Вам сделать выбор о том, какие контроллеры и действия написать: Вы просто структурируете приложение, используя ресурсы, которые создаются, читаются, обновляются, и удаляются. В случае пользователей и микросообщений, этот процесс является простым, так как они - натуральные ресурсы по определению. В Главе 12, мы увидим пример, где принципы REST позволяют нам моделировать более тонкую проблему, “following users”, естественным и удобным способом.
Чтобы исследовать отношения между контроллером Users и моделью User, давайте сосредоточимся на упрощенной версии index
действия, показанную в Листинге 2.4.9
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
возвратить всех пользователей.
app/models/user.rb
class User < ActiveRecord::Base end
Как только @users
переменная определена, контроллер вызывает представление (Шаг 6), показанное в Листинге 2.6. Переменные, которые начинаются со знака @
, называемые переменными экземпляра, автоматически доступны в представлении; в данном случае, представление index.html.erb
в Листинге 2.6 выполняет итерации через список @users
и выводит строку HTML для каждого.10
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, :confirm => 'Are you sure?', :method => :delete %></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, Вам, вероятно, не стОит читать эту книгу.