Nov 11, 2015
Table of contents:
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.
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.
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
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
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
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!