Опубликован: 27.01.2016 | Доступ: свободный | Студентов: 913 / 58 | Длительность: 23:07:00
Лекция 6:

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

Создание пользователя

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

Поскольку мы пока не можем зарегистрироваться через веб-интерфейс — это является целью Главы 7 — мы будем использовать Rails консоль для создания нового пользователя вручную. В отличие от Раздела 6.1.3, в этом разделе мы не должны работать в песочнице, поскольку в этот раз нашей целью является сохранение записи в базе данных:

$ rails console
>> User.create(name: "Michael Hartl", email: "mhartl@example.com",
?>             password: "foobar", password_confirmation: "foobar")
=> #<User id: 1, name: "Michael Hartl", email: "mhartl@example.com",
created_at: "2013-03-11 20:45:19", updated_at: "2013-03-11 20:45:19",
password_digest: "$2a$10$kn4cQDJTzV76ZgDxOWk6Je9A0Ttn5sKNaGTEmT0jU7.n...">

Для того чтобы проверить что это работает, давайте взглянем на строку в девелопмент базе данных (db/development.sqlite3) с помощью SQLite Database Browser ( рис. 6.6). Обратите внимание, что столбцы соответствуют атрибутам модели данных, определенной на рис. 6.5.

Строка пользователя в базе данных SQLite db/development.sqlite3.

Рис. 6.6. Строка пользователя в базе данных SQLite db/development.sqlite3.

Вернувшись в консоль, мы можем увидеть эффект has_secure_password из Листинга 6.29 посмотрев на атрибут password_digest:

>> user = User.find_by(email: "mhartl@example.com")
>> user.password_digest
=> "$2a$10$kn4cQDJTzV76ZgDxOWk6Je9A0Ttn5sKNaGTEmT0jU7.ncBJ/60gHq"

Это зашифрованная версия пароля ("foobar") которая была использована для инициализации объекта user. Мы также можем проверить что команда authenticate работает, использовав вначале невалидный, а затем валидный пароли:

>> user.authenticate("invalid")
=> false
>> user.authenticate("foobar")
=> #<User id: 1, name: "Michael Hartl", email: "mhartl@example.com",
created_at: "2013-03-11 20:45:19", updated_at: "2013-03-11 20:45:19",
password_digest: "$2a$10$kn4cQDJTzV76ZgDxOWk6Je9A0Ttn5sKNaGTEmT0jU7.n...">

Как и требовалось тестами в Листинге 6.28, authenticate возвращает false если пароль невалиден и самого пользователя в противном случае.

Заключение

Начав с нуля, в этой главе мы создали рабочую модель User с name, email и различными "парольными" атрибутами, вместе с валидациями обеспечивающими несколько важных ограничений на их значения. Кроме того, мы можем безопасно аутентифицировать пользователей с помощью пароля. В предыдущих версиях Rails такой подвиг потребовал бы в два раза большего количества кода, но благодаря компактному методу validates и has_secure_password, мы смогли построить рабочую модель User используя меньше дюжины строк исходного кода.

В следующей (седьмой) главе мы сделаем рабочую форму регистрации для создания новых пользователей, вместе со страницей для отображения информации о каждом пользователе. В Главе 8 мы будем использовать механизм аутентификации из Раздела 6.3 для того чтобы дать пользователям возможность входить на сайт.

Если вы используете Git, было бы неплохо закоммитить внесенные изменения, если вы этого еще не сделали:

$ git add .
$ git commit -m "Make a basic User model (including secure passwords)"

Затем опять объединить их с мастер веткой:

$ git checkout master
$ git merge modeling-users

Упражнения

  1. Добавьте тесты для кода отвечающего за перевод email в нижний регистр из Листинга 6.20, как это показано в Листинге 6.30. Этот тест использует метод reload для перезагрузки значения из базы данных и метод eq для тестирования на равенство. Закомменировав строку before_save убедитесь что тесты из Листинга 6.30 тестируют правильные вещи.
  2. Запустив набор тестов убедитесь что коллбэк before_save может быть написан способом показанным в Листинге 6.31.
  3. Как было отмечено в Разделе 6.2.4, регулярное выражение для email в Листинге 6.14 позволяет невалидные адреса электронной почты с последовательно расположенными точками, т.e., адреса вида "foo@bar..com". Добавьте этот адрес в список невалидных адресов в Листинге 6.13 для того чтобы получить провальный тест, а затем с помощью усложненного регулярного выражения показанного в Листинге 6.32 добейтесь прохождения этого теста.
  4. Прочитайте Rails API введение для ActiveRecord::Base для того чтобы получить представление о ее возможностях.
  5. Изучите Rails API введение для метода validates для того чтобы больше узнать о его возможностях и опциях.
  6. Поиграйте пару часов с Rubular.
require 'spec_helper'

describe User do
  .
  .
  .
  describe "email address with mixed case" do
    let(:mixed_case_email) { "Foo@ExAMPle.CoM" }

    it "should be saved as all lower-case" do
      @user.email = mixed_case_email
      @user.save
      expect(@user.reload.email).to eq mixed_case_email.downcase
    end
  end
  .
  .
  .
end
Листинг 6.30. Тест для кода отвечающего за перевод email в нижний регистр из Листинга 6.23. spec/models/user_spec.rb
class User < ActiveRecord::Base
  has_secure_password
  before_save { email.downcase! }
  .
  .
  .
end
Листинг 6.31. Альтернативная реализация before_save. app/models/user.rb
class User < ActiveRecord::Base
  .
  .
  .
  VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-]+(\.[a-z]+)*\.[a-z]+\z/i
  validates :email, presence: true, format: { with: VALID_EMAIL_REGEX },
                    uniqueness: { case_sensitive: false }
  .
  .
  .
end
Листинг 6.32. Регулярное выражение для email запрещающее двойные точки в адресах электронной почты. app/models/user.rb
Вадим Обозин
Вадим Обозин

Здравствуйте, записался на курс. При этом ставил галочку на "обучаться с тьютором". На email пришло письмо, о том, что записался на самостоятельное изучение курса. Как выбрать тьютора?