---
title: ActiveModel Form Objects
teaser:
tags: web,rails
author: Harlow Ward
published_on: 2012-10-10
---

Submitting form data is a common feature of web applications -- allowing users
to submit their information and giving them feedback whether the information is
valid or not.

[ActiveRecord](http://api.rubyonrails.org/classes/ActiveRecord/Base.html) comes
with a powerful set of validators for attributes on a persisted data model. When
data is not persisted, or used for other non-active record purposes, [Active
Model Helper Modules](http://api.rubyonrails.org/classes/ActiveModel.html)
reduce the complexity of validations on your plain old Ruby objects.

## Routing

Create the routes needed for displaying the form object and posting the data

+ Restrict resources to the routes you need using `only:`

```ruby
# config/routes.rb
resources :registration, only: [:new, :create]
```

## Controller and Actions

Create a controller with `new` and `create` actions.

+ `respond_with` will re-render the `new` action if there are any validation
  errors on the model
+ If there are no errors on the model the visitor will be redirected to `show`
  the current resource. In this case the user will be redirected to
  `some_other_success_path`

```ruby
# app/controllers/registration_controller.rb
class RegistrationsController < ApplicationController
  respond_to :html

  def new
    @registration = Registration.new
  end

  def create
    @registration = Registration.new(registration_params)
    @registration.register

    respond_with @registration, location: some_success_path
  end

  private

  def registration_params
    # ...
  end
end
```

## View with Registration Form

The view renders a web form with fields to submit.

+ Use the ActiveModel object `@registration` in the form
+ Form generates the endpoint `registration_path` and method of delivery `post`
+ Validation errors will display inline within the form just like ActiveRecord

```erb
# app/views/registration/new.html.erb
<%= form_for @registration do |f| %>
  <%= f.label :first_name, 'First Name' %>:
  <%= f.text_field :first_name %>
  ...
  <%= f.submit %>
<% end %>
```

## Object with ActiveModel Conversion, Naming, and Validations

Use any of the [ActiveRecord
Validations](http://guides.rubyonrails.org/active_record_validations.html) in
the model.

+ Command pattern used when calling `register` method.
+ ActiveRecord validation syntax on attributes.
+ ActiveModel::Model mixin includes modules, and includes an initialization
  method.

```ruby
# app/models/registration.rb
class Registration
  include ActiveModel::Model

  attr_accessor(
    :company_name,
    :email,
    :first_name,
    :last_name,
    :terms_of_service
  )

  validates :company_name, presence: true
  validates :email, presence: true, email: true
  validates :first_name, presence: true
  validates :last_name, presence: true
  validates :terms_of_service, acceptance: true

  def register
    if valid?
      # Do something interesting here
      # - create user
      # - send notifications
      # - log events, etc.
    end
  end

  private

  def create_user
    # ...
  end
end
```

### Takeaways

+ Keep business logic out of the Controller and Views
+ Add validation support to plain Ruby object using ActiveModel includes
+ Display data validation errors in the form
+ Use ActiveModel naming conventions for generating form endpoints
