Form objects: complex logic
This course covers form objects in Rails: plain Ruby classes that stand in for a model behind one form and hold its context-specific validations. It explains ActiveModel::Model and ActiveModel::Attributes, conditional, custom and cross-field validations, and forms whose fields span several models. It shows how form objects hand validated data to service objects that persist inside a transaction. It also replaces accepts_nested_attributes_for with entry objects and closes with RSpec patterns for testing forms and the form-to-service flow.
What you'll learn
- ✓When a form needs a form object and when model validations are enough
- ✓Typed attributes and form_with integration with ActiveModel::Model and ActiveModel::Attributes
- ✓Conditional, custom and cross-field validations with guard clauses
- ✓Splitting work between controller, form object and service object
- ✓Handling nested child records without accepts_nested_attributes_for
- ✓Testing form objects with RSpec, from unit specs to flow specs
What is a form object?
Imagine a course registration page. The user fills in one form, but behind the scenes that single submission must create a User, an Enrollment and an initial XP award. Which model should validate all those fields? User knows nothing about enrollments, and Enrollment knows nothing about passwords.
Read the full lesson free →Curriculum
7 lessonsWhat is a form object?
Defines form objects and shows how they keep context-specific validations out of models and controllers thin.
ActiveModel::Model & attributes
Explains how ActiveModel::Model and typed attributes let a plain object work with form_with and validations.
Validations in form objects
Covers built-in, conditional, custom and cross-field validations, and where each rule belongs in the layers.
Multi-model forms
Builds one form whose fields span several models, with a service saving everything inside a transaction.
Form objects & service objects together
Walks through a full course transfer flow, separating input validation in the form from business logic.
Nested attributes without accepts_nested_attributes_for
Replaces accepts_nested_attributes_for with entry objects, array parameters and a service that creates parent and children.
Testing form objects
Shows RSpec patterns for testing form validations, guard clauses, edge cases and the handoff to the service.