Проект: Продвинутые формы

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

Проект: Заказ авиабилетов

В этом проекте вы познакомитесь с более сложными формами. Они будут не так просты, как при заказе электронной книги. Здесь будет необходимо выполнить первые три шага типичного заказа полета в один конец:

Вот шаги обычного процесса заказа билета:

  1. Ввести дату вылета/аэропорт и нажать кнопку "Поиск"
  2. Выбрать из списка рейсов подходящий
  3. Ввести информацию о всех пассажирах
  4. Ввести информацию для платежа

Шаг 4 может быть реализован через интеграцию с
Paypal, используя гем или SDK, или используя Stripe.

Ваше задание

Наша программа позволит заказывать билеты в одну сторону. Вы попрактикуетесь в заполнении и создании выпадающих меню, радиокнопок и работе с подчиненными наборами данных. Поехали!

Будет необходимо заполнить таблицы Airports и Flights, для этого используйте файл db/seeds.rb. Для таких тренировочных приложений как это, можно создавать 'seeds' файл, содержащий ::delete_all, а затем заново заполнять таблицы (но не делайте так в реальных приложениях). Таким способом, когда вы создаете новую модель или изменяете настройки в данных, вы можете просто отредактировать seeds.rb, а затем запустить $ rake db:seed.

Настройка

  1. Определитесь с архитектурой таблиц БД для реализации задачи.
  2. Создайте новое приложение, например flight-booker и новый репозиторий Git.
  3. Добавьте в файл README пояснения по этому проекту и ссылку на эту веб-страницу.

Форма 1: Поиск

Для первой страницы нам будет нужен выпадающий список для аэропортов "Из" и "Куда". Предположим, что все полеты осуществляются между SFO и NYC. Необходимо настроить выпадающие списки, которые будут содержать эти значения.

Для этого вам потребуются стандартные формы, которые вы заполните наборами данных. Также вы узнаете нечто новое о работе с датами.

  1. Создайте модель Airport (которая может содержать просто код аэропорта, такой как "SFO" или "NYC") и используйте файл db/seeds.rb для их импорта.
  2. Создайте модель Flight (с полями id аэропортов вылета и прилета, датой вылета и длительностью полета).
  3. Настройте связи между моделями так, чтобы при вызовах Flight.first.from_airport и Flight.first.to_airport вы получали объекты модели Airport. Выполните то же, чтобы при вызове Airport.first.departing_flights и Airport.first.arriving_flights возвращались рейсы.
  4. Заполните таблицу рейсов.
  5. Поиск и просмотр результатов будет осуществляться на одной странице. Настройте контроллер FlightsController и таблицу маршрутов так, чтобы индексная страница /flights была корневой.
  6. Форма поиска на индексной странице должна отправлять запрос GET (а не POST) на этот же URL.
  7. Домашняя страница должна содержать четыре выпадающих списка - аэропорты вылета и прилета, число пассажиров (1-4) и дату вылета. Список с датой вылета должен содержать только даты существующих рейсов. Не переживайте насчет ограничения содержимого списков прилета/вылета - тут можно применить Javascript, так что просто позвольте пользователю выбирать любой аэропорт. Посмотрите пост о форматировании даты в выпадающих списках, этот пост о выборе месяца и года и документацию по DateHelper API для помощи в создании списков выбора даты.

Форма 2: Выбор рейса

Как только пользователь получит список возможных рейсов, ему необходимо выбрать подходящий.

  1. После отправки формы пользователем, контроллер должен определить дополнительные параметры запроса (например /flights?from_code=SFO&to_code=NYC&date=20131215&num_tickets=2) и получить удовлетворяющие им рейсы, используя методы поиска в модели.
  2. Отправьте полученные рейсы в представление app/views/flights/index.html.erb. Результаты (если они имеются) должны отобразиться ниже формы поиска.
  3. Оставьте форму поиска видимой - чтобы пользователь мог запустить новый поиск.
  4. Результаты поиска должны быть в собственной форме - для того, чтобы пользователь мог выбрать необходимый ему рейс. Рядом с каждым полученным рейсом должна находиться радиокнопка - пользователь должен выбрать нужный ему рейс и перейти к следующему шагу. Эта форма должна отправляться на действие #new контроллера BookingsController, используя еще один метод GET. Необходимо будет добавить скрытое поле, содержащее число пассажиров.

Форма 3: Информация о пассажире

Как только пользователь подтверждает свой рейс, необходимо собрать информацию о заказе. Вам понадобится форма для создания заказа и объектов для каждого из пассажиров этого рейса. Не беспокойтесь о создании раздельных объектов типа "Билет" - мы оставим эту часть работы авиакомпании.

  1. Создайте и проведите миграцию модели Booking для заказов.
  2. Сделайте то же самое с моделью Passenger (не усложняйте ее - добавьте только поля с именем и email).
  3. Настройте связи между моделями Booking, Passenger и Flight.
  4. Создайте контроллер BookingsController и соответствующие маршруты.
  5. Настройте действие #new, которое принимает ID рейса и количество пассажиров и использует их для рендеринга формы заказа, которая в свою очередь содержит дату вылета, аэропорты, ID рейса и набор полей для ввода персональных данных по каждому пассажиру. Необходимо будет создать пустой объект модели Passenger в контроллере для каждого пассажира, а затем использовать #fields_for в представлении для подчиненных форм.
  6. Отправьте форму и проверьте параметры, отправляемые на сервер.
  7. Действие #create должно создавать новый заказ (связывая его с соответствующим рейсом), но также должно принимать вложенные атрибуты для каждого из пассажиров для их создания. Хорошо обдумайте работу с белым списком вложенных параметров.
  8. Создайте метод #accepts_nested_attributes_for в модели Booking. В качестве помощи посмотрите Rails API и этот пост.
  9. После отправки формы должна отображаться страница #show, содержащая информацию по заказу (рейс и список пассажиров).
  10. Проверьте работоспособность программы в целом. Неплохая работа!

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

Дополнительные ресурсы

Этот раздел содержит полезные ссылки на дополнительные материалы. Это не обязательно, так что расценивайте их как нечто полезное, если вы хотите поглубже погрузиться в тему

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