Проекты: Формы
Не забывайте использовать Git для фиксации изменений в ваших проектах!
В этих проектах вам предстоит создавать формы, начиная с почти чистого HTML и постепенно задействуя предоставляемые Rails методы-помощники. Также освещается интеграция формы регистрации пользователей с вашим приложением Rails, а также вывод информации об ошибках валидации.
Проект 1: Простые формы и помощники
Вам предстоит создать форму старым добрым способом, а затем пойти по пути Rails.
Задание
Настройка бэкенда
В последующих уроках вы научитесь быстро создавать и настраивать приложения, используя следующие шаги (и мы будем помогать вам с ними все меньше и меньше в дальнейшем):
- Создайте новое приложение "re-former".
- Перейдите в папку с приложением и создайте репозиторий Git. Проведите первичный commit.
- Внесите в файл README что-то говорящее о приложении, например "Это часть проекта Формы с сайта http://codenamecrud.ru/"
- Создайте модель User с полями
:username
,:email
и:password
и проведите ее миграцию. - Добавьте валидации для проверки наличия каждого поля в модели.
- Добавьте в файл маршрутов ресурс
:users
. Используйте опцию:only
, чтобы указать только действия:new
и:create
. - Создайте контроллер UsersController (или вручную, или используя генератор
$ rails generate controller Users
). - Напишите в нем пустые методы
#new
и#create
. - Создайте вьюху
#new
вapp/views/users/new.html.erb
. - Запустите сервер rails в другом окне терминала.
- Проверьте что все работает корректно, открыв
http://localhost:3000/users/new
в браузере.
Форма HTML
Первую форму вы создадите на HTML (еще помните, что это такое?). Для этого внесите соответствующие изменения в app/views/users/new.html.erb
. Наша цель - сделать ее почти идентичной той форме, которую вы получали при использовании помощников Rails, таким образом вы сможете лучше понять, как они реализованы.
- Сделайте форму для создания пользователя. Если забыли, как это делается, посмотрите документацию по формам от w3. Укажите атрибуты
method
иaction
в тэге<form>
(используйте$ rake routes
чтобы удостовериться в корректности метода HTTP и действия). Включите также атрибутaccept-charset="UTF-8"
, который Rails автоматически добавляет для декодирования символов Юникод. - Создайте необходимые теги
input
для необходимых полей (email, username и password). Используйте специальныйinput
для поля с паролем. Проверьте, что для всех тэгов указан атрибутname
. Создайте тэгиlabel
для каждого поля. - Отправьте форму и посмотрите лог сервера. Упс, у нас нет метки CSRF (
ActionController::InvalidAuthenticityToken
), защищающей от межсайтовых атак. - Создайте собственную метку, добавив скрытое поле ввода и используя метод
#form_authenticity_token
. Этот метод проверяет метку этой сессии, которую Rails сохранил для пользователя (это произошло в фоне) и добавляет ее в форму, поэтому становится возможным проверить, что именно вы отправили форму. Это может выглядеть так:
# app/views/users/new.html.erb
...
<input type="hidden" name="authenticity_token" value="<%= form_authenticity_token %>">
...
- Отправьте форму заново. Успешно! Но, мы получили ошибку
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"=>"[email protected]", "password"=>"[FILTERED]"}
Очень похоже на лог обычного Rails приложения, не так ли?
- Откройте 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
- Проверьте - сможете вы сейчас создавать пользователей из этой формы?
- Это не все.. код для создания пользователя выглядит слишком длинным и сложным с этой кучей вызовов
params
. Мы могли бы его упростить, используя хэш атрибутов пользователя, что-то вродеUser.new(user_params)
. Для этого форма должна отправить хэш атрибутов, которые будут использованы для создания пользователя, подобно тому, как это делает методform_for
. Как мы помним, он отправляет полеuser
верхнего уровня, которое на самом деле указывает на хэш значений. Это нетрудно сделать - просто немного измените атрибутname
. Заключите ваши три атрибута пользователя в квадратные скобки внутри атрибута переменной, напримерname="user[email]"
. - Отправьте форму. Теперь параметры пользователя должны быть внутри ключа
"user"
:
Parameters: {"authenticity_token"=>"WUaJBOpLhFo3Mt2vlEmPQ93zMv53sDk6WFzZ2YJJQ0M=", "user" => {"username"=>"foobar", "email"=>"[email protected]", "password"=>"[FILTERED]"}}
- Вы получите ошибки в логе, так как теперь необходимо изменить контроллер. Но помните, что теперь нельзя вызвать напрямую
params[:user]
, так как это вернет хэш, а из соображений безопасности Rails это запрещает, до момента его валидации. - Закомментируйте в действии
#create
контроллера строчку, в которой создавался пользователь (она нам пригодится позже). - Создайте в конце файла приватный метод
user_params
дляpermit
иrequire
нужных полей (чтобы освежить в памяти этот материал, можете посмотреть урок по контроллерам). - Добавьте строчку создания пользователя, в которой будет использоваться новый метод "белого списка" параметров.
- Теперь отправьте форму. Она должна отлично работать (как только вы исправите свои опечатки)!
Рельсовые формы с #form_tag
Теперь изменим форму в полноценную форму Rails, используя помощники #form_tag
и #*_tag
. Здесь будет немного пользы от помощников, и вы увидите, что в основном придется просто переименовать теги HTML на теги Rails.
- Полностью закомментируйте HTML форму. Это может пригодиться, если в будущем вы на чем-то застрянете.
- Преобразуйте тег
<form>
для использования помощника#form_tag
, а все поля ввода на соответствующие методы#*_tag
. Хорошая новость здесь в том, что теперь нам больше не нужно поле с меткой CSRF, так как Rails добавит ее автоматически. - Посмотрите документацию по API, чтобы ознакомиться с перечнем и использованием всех методов, которые вы можете использовать с
#form_tag
. - Протестируйте свою форму. Необходимо будет внести изменения в действие
#create
контроллера, чтобы снова принимать обычные пользовательские атрибуты верхнего уровня, так что раскомментируйте старую строкуUser.new
и закомментируйте текущую. - Тут мы закончим первый шаг.
Рельсификация форм с #form_for
#form_tag
не выглядит особо полезным - работы с ним почти столько же, сколько и при использовании тега <form>
, кроме пожалуй момента с использованием токена аутентификации. Давайте преобразуем его в #form_for
, который использует объекты модели для создания формы.
- Измените действие
#new
в контроллере для создания пустого объекта User и сохранения его в переменной экземпляра@user
. - Закомментируйте форму
#form_tag
вapp/views/users/new.html.erb
(теперь у вас должно быть два закомментированных примера формы). - Перепишите форму, используя
#form_for
и переменную@user
из контроллера. - Поиграйте с опциями метода
#input
- добавьте содержание по умолчанию (например "[email protected]" для поля email), сделайте другое название поля (например "Введите в это поле имя пользователя") и попробуйте получить в поле ввода какие-либо данные. Кое-что вам придется погуглить, но также можно посмотреть документацию по#form_for
. - Проверьте работоспособность. Вам понадобится снова переключить метод
#create
, чтобы он принимал хэш:user
изparams
.
Редактирование
- Внесите изменения в маршруты и контроллер, чтобы можно было редактировать существующего пользователя. Контроллер должен будет найти пользователя по отправленному формой полю ID в
params
. - Создайте соответствующее представление
app/views/users/edit.html.erb
и скопируйте в нее содержимое формыNew
. Ваш HTML и#form_tag
(которые должны быть до сих пор закомментированы) работать не будут - они отправят запрос POST, в то время как это должен быть запрос PATCH (PUT) - помните$ rake routes
? Внесите несложные исправления в код, которые будут видны при попытке редактирования пользователя в форме#form_for
(она достаточно разумна, чтобы определить, хотите ли вы редактировать пользователя, или же создать нового). - Выберите "исходный код страницы" на форме редактирования, сгенерированной
#form_for
. Обратите внимание на скрытые поля наверху, заключенные в<div>
. Видите? - Попробуйте отправить отредактированную заведомо невалидными данными форму.
#form_for
автоматически обработает форму особенным образом (например красной рамкой на поле ввода) если он обнаружит ошибки валидации. - Сохраните проект в Git и отправьте его на Github.
Дополнительно
- Заставьте форму отобразить список ошибок, возникающих при валидации объекта модели. Вспомните методы
#errors
и#full_messages
и используйте их.
Решения студентов
Проект 2: Учебник Ruby on Rails
Здесь вы примените свои знания в реальном приложении, а не просто в примерах. Вы создадите форму регистрации пользователей и подключите ее к валидациям, которые вы ранее создали в БД.
Ваши задания
- Выполните главу 7 из учебника по Ruby on Rails, "Регистрация".