0
0
Ruby on Railsframework~5 mins

Form object pattern in Ruby on Rails

Choose your learning style9 modes available
Introduction

The form object pattern helps keep your code clean by separating form handling from your database models. It makes complex forms easier to manage and test.

When a form needs to update multiple models at once.
When you want to keep your database models simple and focused.
When you have complex validation logic that doesn't fit well in a single model.
When you want to reuse form logic across different parts of your app.
When you want to test form behavior without touching the database.
Syntax
Ruby on Rails
class MyForm
  include ActiveModel::Model

  attr_accessor :field1, :field2

  validates :field1, presence: true

  def save
    return false unless valid?
    # custom save logic here
  end
end

Use include ActiveModel::Model to get model-like behavior without a database table.

Define attr_accessor for form fields you want to handle.

Examples
A form object for user signup that validates email and password confirmation, then creates a User.
Ruby on Rails
class SignupForm
  include ActiveModel::Model

  attr_accessor :email, :password, :password_confirmation

  validates :email, presence: true
  validates :password, confirmation: true

  def save
    return false unless valid?
    User.create(email: email, password: password)
  end
end
This form object handles order creation with validations for product and quantity.
Ruby on Rails
class OrderForm
  include ActiveModel::Model

  attr_accessor :product_id, :quantity, :user_id

  validates :product_id, :quantity, presence: true

  def save
    return false unless valid?
    Order.create(product_id: product_id, quantity: quantity, user_id: user_id)
  end
end
Sample Program

This ContactForm object collects user input, validates presence of all fields, and simulates saving by returning true. It prints success or error messages.

Ruby on Rails
class ContactForm
  include ActiveModel::Model

  attr_accessor :name, :email, :message

  validates :name, :email, :message, presence: true

  def save
    return false unless valid?
    # Imagine sending an email here
    true
  end
end

# Usage example
form = ContactForm.new(name: "Alice", email: "alice@example.com", message: "Hello!")
if form.save
  puts "Form saved successfully"
else
  puts "Form has errors: #{form.errors.full_messages.join(", ")}"
end
OutputSuccess
Important Notes

Form objects do not connect directly to the database like ActiveRecord models.

They are great for complex forms that touch multiple models or need custom validation.

Remember to test form objects separately from your database models.

Summary

Form objects keep form logic separate from database models.

They use ActiveModel::Model to behave like models without a table.

They help manage complex forms and validations cleanly.