Last week we looked at using Form Objects to remove some of the burden of validation from our Active Record models.

A Form Object is basically just a plain Ruby Object that is able to quack like an Active Record object.

One thing that I mentioned, but skipped over last week was Active Model.

Active Model is a library of modules used for developing classes that need certain aspects of Active Record’s functionality.

In today’s tutorial we will be looking at using Active Model.

What is Active Model?

As I mentioned in Getting started with Active Record in Ruby on Rails, Ruby on Rails has a very powerful implementation of the Active Record pattern.

Active Record also has a lot of functionality that would be useful outside of the ORM.

For example, validations, serialisations, and translations are important aspects of ActiveRecord, but could also be used outside of the context of an ORM.

To prevent reinventing the wheel every time you wanted to add this kind of functionality to other Ruby objects, Active Model was abstracted from Active Record.

This makes it very easy to add this functionality to your ruby objects.

Active Model is basically just a set of modules you can include in your Ruby objects to add certain aspects of functionality from Active Record.

Validation

One aspect of Active Model that we’ve already seen is Validation.

Validation is a very important aspect of a web application, but it doesn’t always occur only in the model.

As we saw in last week’s tutorial we could also use Form Objects for particular processes like registration, resetting passwords or other common processes that require data input from the user.

Validation is also important when creating Domain Objects to represent core components of your application.

For example, imagine we had a Book class:

class Book
end

A book should always have an title and a isbn in order for it to be “valid”.

We can ensure that this is the case by including ActiveModel::Validations:

class Book
  include ActiveModel::Validations

  attr_accessor :name, :isbn

  validates :name, presence: true
  validates :isbn, presence: true
end

Now we can use the Book class like any other object, but we now have the power of Active Model Validations:

book = Book.new
book.valid? # false

book.name = 'The Four Hour Work Week'
book.isbn = '123'
book.valid? # true

Dirty

Another useful module you can include on your plain Ruby objects is the Dirty module. This will allow you to detect if any of the properties of the object have been changed:

class Book
  include ActiveModel::Dirty
  define_attribute_methods :name, :isbn

  def name
    @name
  end

  def name=(value)
    name_will_change!
    @name = value
  end

  def isbn
    @isbn
  end

  def isbn=(value)
    isbn_will_change!
    @isbn = value
  end
end

Now you can query the object to see if any of the properties have changed:

book = Book.new
book.changed? # false

book.name = 'Crushing it!'
book.changed? # true

book.changes # {"name"=>[nil, "Crushing it!"]}

book.name_changed? # true
book.isbn_changed? # false

book.name_was # nil
book.name_change # [nil, "Crushing it!"]

book.isbn_was # nil
book.isbn_change # nil

Serialisation

The Serialisation module allows you to serialise your objects into a number of different formats.

class Book
  include ActiveModel::Serializers::JSON

  attr_accessor :name, :isbn

  def attributes
    { 'name' => nil, 'isbn' => nil }
  end
end

Your Ruby object will now have access to the as_json method to return the object as JSON:

book = Book.new
book.name = 'Fooled by Randomness'
book.isbn = '123'

book.as_json # {"name":"Fooled by Randomness","isbn":"123"}

If you wanted to switch from JSON to XML, you will only need to change the included module:

class Book
  include ActiveModel::Serializers::XML

  attr_accessor :name, :isbn

  def attributes
    { 'name' => nil, 'isbn' => nil }
  end
end

Conclusion

By abstracting these common modules out of Active Record, we have been blessed with a very simply way of adding certain types of functionality to our ruby objects.

Nobody in their right mind wants to write a validation library from scratch, and so simply including the already build Active Record validation module is as simple as can be.

As we saw in last week’s tutorial, sometimes we need an object that can quack like an Active Record object. By using the modules of Active Model, this is a very easy thing to accomplish!