Проекты: Формы

Не забывайте использовать Git для фиксации изменений в ваших проектах!

В этих проектах вам предстоит создавать формы, начиная с почти чистого HTML и постепенно задействуя предоставляемые Rails методы-помощники. Также освещается интеграция формы регистрации пользователей с вашим приложением Rails, а также вывод информации об ошибках валидации.

Проект 1: Простые формы и помощники

Вам предстоит создать форму старым добрым способом, а затем пойти по пути Rails.

Задание

Настройка бэкенда

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

  1. Создайте новое приложение "re-former".
  2. Перейдите в папку с приложением и создайте репозиторий Git. Проведите первичный commit.
  3. Внесите в файл README что-то говорящее о приложении, например "Это часть проекта Формы с сайта http://codenamecrud.ru/"
  4. Создайте модель User с полями :username, :email и :password и проведите ее миграцию.
  5. Добавьте валидации для проверки наличия каждого поля в модели.
  6. Добавьте в файл маршрутов ресурс :users. Используйте опцию :only, чтобы указать только действия :new и :create.
  7. Создайте контроллер UsersController (или вручную, или используя генератор $ rails generate controller Users).
  8. Напишите в нем пустые методы #new и #create.
  9. Создайте вьюху #new в app/views/users/new.html.erb.
  10. Запустите сервер rails в другом окне терминала.
  11. Проверьте что все работает корректно, открыв http://localhost:3000/users/new в браузере.

Форма HTML

Первую форму вы создадите на HTML (еще помните, что это такое?). Для этого внесите соответствующие изменения в app/views/users/new.html.erb. Наша цель - сделать ее почти идентичной той форме, которую вы получали при использовании помощников Rails, таким образом вы сможете лучше понять, как они реализованы.

  1. Сделайте форму для создания пользователя. Если забыли, как это делается, посмотрите документацию по формам от w3. Укажите атрибуты method и action в тэге <form> (используйте $ rake routes чтобы удостовериться в корректности метода HTTP и действия). Включите также атрибут accept-charset="UTF-8", который Rails автоматически добавляет для декодирования символов Юникод.
  2. Создайте необходимые теги input для необходимых полей (email, username и password). Используйте специальный input для поля с паролем. Проверьте, что для всех тэгов указан атрибут name. Создайте тэги label для каждого поля.
  3. Отправьте форму и посмотрите лог сервера. Упс, у нас нет метки CSRF (ActionController::InvalidAuthenticityToken), защищающей от межсайтовых атак.
  4. Создайте собственную метку, добавив скрытое поле ввода и используя метод #form_authenticity_token. Этот метод проверяет метку этой сессии, которую Rails сохранил для пользователя (это произошло в фоне) и добавляет ее в форму, поэтому становится возможным проверить, что именно вы отправили форму. Это может выглядеть так:
    # app/views/users/new.html.erb
    ...
    <input type="hidden" name="authenticity_token" value="<%= form_authenticity_token %>">
    ...
  1. Отправьте форму заново. Успешно! Но, мы получили ошибку Template is missing, что говорит о том, что мы успешно прошли через пустое действие #create в контроллере (и не указали, что должно произойти дальше, поэтому Rails ищет представление по умолчанию app/views/users/create.html.erb). Посмотрите лог сервера повыше ошибки. Он должен содержать отправленные параметры, например:
    Started POST "/users" for 127.0.0.1 at 2013-12-12 13:04:19 -0800
    Processing by UsersController#create as HTML
    Parameters: {"authenticity_token"=>"WUaJBOpLhFo3Mt2vlEmPQ93zMv53sDk6WFzZ2YJJQ0M=", "username"=>"foobar", "email"=>"foo@bar.com", "password"=>"[FILTERED]"}

Очень похоже на лог обычного Rails приложения, не так ли?

  1. Откройте UsersController и сделайте, чтобы действие #create создавало нового пользователя на основании параметров, пришедших из формы. Если пользователь успешно сохранится в базе, то должно произойти перенаправление (редирект) на создание нового пользователя. В противном случае, отрендерите форму :new заново (при этом она будет содержать введенную вами в нее информацию). Вам надо сделать что-то вроде:
    # app/controllers/users_controller.rb
    def create
      @user = User.new(username: params[:username], email: params[:email], password: params[:password])
      if @user.save
        redirect_to new_user_path
      else
        render :new
      end
    end
  1. Проверьте - сможете вы сейчас создавать пользователей из этой формы?
  2. Это не все.. код для создания пользователя выглядит слишком длинным и сложным с этой кучей вызовов params. Мы могли бы его упростить, используя хэш атрибутов пользователя, что-то вроде User.new(user_params). Для этого форма должна отправить хэш атрибутов, которые будут использованы для создания пользователя, подобно тому, как это делает метод form_for. Как мы помним, он отправляет поле user верхнего уровня, которое на самом деле указывает на хэш значений. Это нетрудно сделать - просто немного измените атрибут name. Заключите ваши три атрибута пользователя в квадратные скобки внутри атрибута переменной, например name="user[email]".
  3. Отправьте форму. Теперь параметры пользователя должны быть внутри ключа "user":
    Parameters: {"authenticity_token"=>"WUaJBOpLhFo3Mt2vlEmPQ93zMv53sDk6WFzZ2YJJQ0M=", "user" => {"username"=>"foobar", "email"=>"foo@bar.com", "password"=>"[FILTERED]"}}
  1. Вы получите ошибки в логе, так как теперь необходимо изменить контроллер. Но помните, что теперь нельзя вызвать напрямую params[:user], так как это вернет хэш, а из соображений безопасности Rails это запрещает, до момента его валидации.
  2. Закомментируйте в действии #create контроллера строчку, в которой создавался пользователь (она нам пригодится позже).
  3. Создайте в конце файла приватный метод user_params для permit и require нужных полей (чтобы освежить в памяти этот материал, можете посмотреть урок по контроллерам).
  4. Добавьте строчку создания пользователя, в которой будет использоваться новый метод "белого списка" параметров.
  5. Теперь отправьте форму. Она должна отлично работать (как только вы исправите свои опечатки)!

Рельсовые формы с #form_tag

Теперь изменим форму в полноценную форму Rails, используя помощники #form_tag и #*_tag. Здесь будет немного пользы от помощников, и вы увидите, что в основном придется просто переименовать теги HTML на теги Rails.

  1. Полностью закомментируйте HTML форму. Это может пригодиться, если в будущем вы на чем-то застрянете.
  2. Преобразуйте тег <form> для использования помощника #form_tag, а все поля ввода на соответствующие методы #*_tag. Хорошая новость здесь в том, что теперь нам больше не нужно поле с меткой CSRF, так как Rails добавит ее автоматически.
  3. Посмотрите документацию по API, чтобы ознакомиться с перечнем и использованием всех методов, которые вы можете использовать с #form_tag.
  4. Протестируйте свою форму. Необходимо будет внести изменения в действие #create контроллера, чтобы снова принимать обычные пользовательские атрибуты верхнего уровня, так что раскомментируйте старую строку User.new и закомментируйте текущую.
  5. Тут мы закончим первый шаг.

Рельсификация форм с #form_for

#form_tag не выглядит особо полезным - работы с ним почти столько же, сколько и при использовании тега <form>, кроме пожалуй момента с использованием токена аутентификации. Давайте преобразуем его в #form_for, который использует объекты модели для создания формы.

  1. Измените действие #new в контроллере для создания пустого объекта User и сохранения его в переменной экземпляра @user.
  2. Закомментируйте форму #form_tag в app/views/users/new.html.erb (теперь у вас должно быть два закомментированных примера формы).
  3. Перепишите форму, используя #form_for и переменную @user из контроллера.
  4. Поиграйте с опциями метода #input - добавьте содержание по умолчанию (например "example@example.com" для поля email), сделайте другое название поля (например "Введите в это поле имя пользователя") и попробуйте получить в поле ввода какие-либо данные. Кое-что вам придется погуглить, но также можно посмотреть документацию по #form_for.
  5. Проверьте работоспособность. Вам понадобится снова переключить метод #create, чтобы он принимал хэш :user из params.

Редактирование

  1. Внесите изменения в маршруты и контроллер, чтобы можно было редактировать существующего пользователя. Контроллер должен будет найти пользователя по отправленному формой полю ID в params.
  2. Создайте соответствующее представление app/views/users/edit.html.erb и скопируйте в нее содержимое формы New. Ваш HTML и #form_tag (которые должны быть до сих пор закомментированы) работать не будут - они отправят запрос POST, в то время как это должен быть запрос PATCH (PUT) - помните $ rake routes? Внесите несложные исправления в код, которые будут видны при попытке редактирования пользователя в форме #form_for (она достаточно разумна, чтобы определить, хотите ли вы редактировать пользователя, или же создать нового).
  3. Выберите "исходный код страницы" на форме редактирования, сгенерированной #form_for. Обратите внимание на скрытые поля наверху, заключенные в <div>. Видите?
  4. Попробуйте отправить отредактированную заведомо невалидными данными форму. #form_for автоматически обработает форму особенным образом (например красной рамкой на поле ввода) если он обнаружит ошибки валидации.
  5. Сохраните проект в Git и отправьте его на Github.

Дополнительно

  1. Заставьте форму отобразить список ошибок, возникающих при валидации объекта модели. Вспомните методы #errors и #full_messages и используйте их.

Решения студентов

Проект 2: Учебник Ruby on Rails

Здесь вы примените свои знания в реальном приложении, а не просто в примерах. Вы создадите форму регистрации пользователей и подключите ее к валидациям, которые вы ранее создали в БД.

Ваши задания

  1. Выполните главу 7 из учебника по Ruby on Rails, "Регистрация".

Поделиться уроком: