Обработка данных форм - фундаментальная задача веб-разработки. Рассмотрим полный цикл работы с формами в Ruby-экосистеме.
Самый базовый способ, работающий во всех фреймворках:
<form action="/submit" method="post">
<input type="text" name="user[name]">
<input type="email" name="user[email]">
<button type="submit">Отправить</button>
</form>
Обработка в Sinatra:
post '/submit' do
name = params[:user][:name]
email = params[:user][:email]
# Обработка данных...
end
Rails предоставляет мощные хелперы для работы с формами:
<%= form_with model: @user do |form| %>
<%= form.text_field :name %>
<%= form.email_field :email %>
<%= form.submit %>
<% end %>
Контроллер Rails:
def create
@user = User.new(user_params)
if @user.save
redirect_to @user
else
render :new
end
end
private
def user_params
params.require(:user).permit(:name, :email)
end
class User < ApplicationRecord
validates :name, presence: true
validates :email,
presence: true,
format: { with: URI::MailTo::EMAIL_REGEXP },
uniqueness: true
end
Защита от массового назначения атрибутов:
def user_params
params.require(:user).permit(:name, :email, :age)
end
<%= form.file_field :avatar %>
Контроллер:
def user_params
params.require(:user).permit(:name, :email, :avatar)
end
// Пример с Activestorage
input.addEventListener('change', (event) => {
const files = event.target.files;
Array.from(files).forEach(file => uploadFile(file))
});
CSRF-защита:
Экранирование HTML:
text_field
ERB::Util.html_escape(str)
Параметры запроса:
params.to_unsafe_h
без необходимости<%= form_with model: @user, local: false do |form| %>
<!-- поля формы -->
<% end %>
Обработка ответа:
$(document).on('ajax:success', 'form', function(event) {
const [data, status, xhr] = event.detail;
// Обработка успешного ответа
});
fetch('/users', {
method: 'POST',
body: new FormData(formElement)
})
.then(response => response.json())
.then(data => console.log(data));
Для сложных форм можно использовать:
Form Objects:
class RegistrationForm
include ActiveModel::Model
attr_accessor :name, :email, :password
validates :email, format: { with: URI::MailTo::EMAIL_REGEXP }
# ... другие валидации
end
Dry-validation:
schema = Dry::Schema.Params do
required(:name).filled(:string)
required(:email).filled(:string, format?: URI::MailTo::EMAIL_REGEXP)
end
test "create user" do
visit new_user_path
fill_in 'Name', with: 'Test User'
fill_in 'Email', with: 'test@example.com'
click_button 'Create User'
assert_text 'User was successfully created'
end
test "should create user" do
assert_difference('User.count') do
post users_url, params: { user: { name: 'Test', email: 'test@example.com' } }
end
end
Обработка форм включает:
Ключевые практики: