# coding: utf-8

2.2.2 MVC в действии

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

Рисунок 2.11: Подробная схема MVC в Rails.

Рисунок 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 в браузер 7

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

Листинг 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). Отметьте в Таблице 2.2, что есть некоторое наложение в URL; например, и user show и update действиям соответствует URL /users/1. Различие между ними в методе запроса HTTP на который они отвечают. Мы узнаем больше о методах запроса HTTP в Разделе 3.2.2.

HTTP запрос URL Действие Назначение (цель)
GET/usersindexстраница, со списком всех пользователей
GET/users/1showстраница, показывающая пользователя с id 1
GET/users/newnewстраница, чтобы сделать нового пользователя
POST/userscreateсоздание нового пользователя
GET/users/1/editeditстраница для редактирования пользователя с id 1
PUT/users/1updateобновление пользователя с id 1
DELETE/users/1destroyудаление пользователя с id 1

Таблица 2.2: RESTful маршруты, обеспеченные ресурсом Users в Листинге 2.2.
Блок 2.2. REST (REpresentational State Transfer, («передача состояния представления»))

Если Вы много читали о веб-разработке 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

Листинг 2.4. Упрощенное user 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 для каждого.10

Листинг 2.6. Представление для user 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, :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, Вам, вероятно, не стОит читать эту книгу.
# coding: utf-8