Как делать многоуровневые формы в Rails

от автора

Привет, Хабр!

Работа с многоуровневыми формами в Ruby on Rails — это то, что точно поднимет ваш скилл в Ruby. В этой рассмотрим, как упростить этот процесс с помощью двух гемов: Wicked и Cocoon.

Многоуровневые формы позволяют собирать информацию от пользователя поэтапно, что делает интерфейс более дружелюбным.

Настройка и конфигурация гемов Wicked и Cocoon для Rails

Wicked

Для начала добавляем Wicked в Gemfile:

gem 'wicked'

Затем выполняем команду bundle install для установки гема.

Wicked превращает контроллер в магический многоэтапный процесс. Начинаем с создания нового контроллера или модификации существующего, добавив в него миксин Wicked::Wizard. Например:

rails g controller after_signup

В контроллер добавляем:

include Wicked::Wizard steps :first_step, :second_step

В config/routes.rb указываем, что контроллер должен использовать магические маршруты:

resources :after_signup, only: [:show, :update], controller: 'after_signup'

Юзаем render_wizard для управления переходами между шагами. Например:

def show   @user = current_user   render_wizard end

В update методе можно обработать ввод данных и переход к след. шагу.

Cocoon

Аналогично как и с Wicked, добавляем следующую строку в Gemfile:

gem 'cocoon'

Выполняемbundle install.

С Cocoon можно легко работать с вложенными атрибутами, например в форме можно использовать link_to_add_association и link_to_remove_association для динамического добавления или удаления полей.

Пример использования в форме с помощью simple_form:

<%= simple_form_for @user do |f| %>   <%= f.simple_fields_for :addresses do |address| %>     <%= render 'address_fields', f: address %>   <% end %>   <%= link_to_add_association 'add address', f, :addresses %> <% end %>

В частичном представлении _address_fields.html.erb можно использовать link_to_remove_association для добавления возможности удаления.

Cocoon автоматически работает с jQuery через application.js:

//= require jquery //= require cocoon

На стороне клиента можно использовать события Cocoon, такие как cocoon:before-insert и cocoon:after-insert, для добавления пользовательских анимаций или логики обработки:

$(document).on('cocoon:before-insert', function(e, insertedItem) {   // анимация или другие действия перед вставкой элемента   insertedItem.fadeIn('slow'); });  $(document).on('cocoon:after-insert', function(e, insertedItem) {   // действия после вставки элемента });

Обработка и валидация данных формы

Rails предоставляет множество хелперов для валидации, таких как presence, length, numericality, и format, которые помогают убедиться, что данные соответствуют определённым требованиям. Например, чтобы убедиться, что поле не пустое и соответствует определённой длине, можно использовать следующие валидации в модели:

class Comment < ApplicationRecord   validates :content, presence: true, length: { maximum: 500 } end

Если данные не проходят валидацию, объект не будет сохранён в БД, а ошибки можно будет проверить через метод errors объекта.

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

class Comment < ApplicationRecord   validate :check_for_offensive_language    private    def check_for_offensive_language     if content.include?('offensive_word')       errors.add(:content, 'contains offensive language')     end   end end

При работе с формами и API, важно правильно обрабатывать ошибки валидации и передавать их юзеру. В контроллере можно организовать проверку валидности объекта и соответствующим образом формировать ответ:

class UsersController < ApplicationController   def create     user = User.new(user_params)     if user.save       render json: user, status: :created     else       render json: { errors: user.errors.full_messages }, status: :unprocessable_entity     end   end    private    def user_params     params.require(:user).permit(:name, :email, :password)   end end

Так можно отображать пользователю конкретные ошибки, связанные с каждым полем формы.

Тестирование

Для тестирования многоуровневых форм рекомендуется использовать сочетание RSpec и Capybara:

describe "Multi-step form", type: :feature do   it "processes the form correctly" do     visit new_registration_path     fill_in 'Name', with: 'Kolya'     click_button 'Next'     fill_in 'Address', with: '123 Lenina St'     click_button 'Submit'     expect(page).to have_content('Registration successful')   end end

Для детальной отладки можете использовать гем Pry. С ним можно остановить выполнение кода в любой точке и изучить текущее состояние переменных и логику выполнения:

class RegistrationsController < ApplicationController   def create     binding.pry  # остановка и отладка в этой точке     @user = User.new(user_params)     if @user.save       redirect_to @user     else       render :new     end   end end

Также не забываем логировать основные парамтеры:

Rails.logger.debug "Processing step 1 with data: #{params[:user]}"

Для более сложных многоуровневых форм можно юзать интеграционные тесты. Создавайте тестовые объекты с помощью FactoryBot и проверяйте ассоциации и валидации с помощью Shoulda Matchers:

describe User, type: :model do   it { should validate_presence_of(:email) }   it "has a valid factory" do     user = build(:user)     expect(user).to be_valid   end end

Все лучшие практики веб-разработки на Ruby on Rails можно освоить на практическом онлайн-курсе.


ссылка на оригинал статьи https://habr.com/ru/articles/812305/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *