Восемь лет писал на Laravel, полгода как на Rails 7.0. Привык, что валидация входящих данных живёт в отдельном классе FormRequest, а модель про форму ничего не знает. Здесь все валидации пишут в модели, но у меня форма регистрации компании создаёт сразу компанию и первого пользователя. Пихать в Company проверку длины пароля как-то неправильно. В Laravel это был бы класс с методом rules() и массивом правил, а контроллер получал бы уже проверенные данные. В Rails пока вижу два пути: валидации в модели с on: :registration или колбэки, и оба выглядят костылями. Ruby 3.2, если важно. Как вы такое раскладываете?
Для такого делают form object на ActiveModel::Model. Это обычный класс, который умеет валидации, ошибки и form_with, а сохранение ты пишешь сам, в транзакции:
class CompanyRegistration
include ActiveModel::Model
include ActiveModel::Attributes
attribute :company_name, :string
attribute :email, :string
attribute :password, :string
validates :company_name, :email, presence: true
validates :password, length: { minimum: 10 }
def save
return false unless valid?
ActiveRecord::Base.transaction do
company = Company.create!(name: company_name)
company.users.create!(email: email, password: password)
end
true
end
end
В контроллере @form = CompanyRegistration.new(registration_params) и if @form.save, в шаблоне form_with model: @form, url: registrations_path. Валидации, которые нужны данным всегда (уникальность email, формат), оставь в модели, а то, что касается только этой формы, сюда. Если create! всё-таки упадёт на модельной валидации, поймай ActiveRecord::RecordInvalid и перенеси ошибки в errors формы, иначе пользователь увидит 500.
В Go это структура с тегами валидации, и никаких споров, где она живёт. Rails любит решать за тебя
Если хочется прямо как FormRequest, отдельным слоем, посмотри dry-validation. В Roda без него никак, там модели про формы вообще не знают: описываешь схему с правилами, на выходе либо чистый хеш, либо ошибки. Для Rails это не обязательно, ActiveModel::Model закрывает большую часть случаев, но мысль та же.