Rails 7 introduces ActiveModel::API


When working with Rails, we are familiar with ActiveRecord. Active Record is the Model in the MVC framework that is the layer of the system responsible for representing business data and logic. It’s an ORM that connects the rich objects of an application to tables in a relational database management system.

We come across cases where classes in Rails require model-like features, but they are not tied to any table in a database. That is where Rails ActiveModel comes into picture. It’s a library used in developing classes that need some features present on Active Record.

Let’s say we have a Person class with name and id attributes. We want to add validations to these attributes. With ActiveModel we can implement Person class as below:

class Person
  include ActiveModel::Model

  attr_accessor :name, :email
  validates :name, :email, presence: true
end

irb> person = Person.new(name: "Sam", email: "sam@example.com")

irb> person.name
=> "Sam"

irb> person.email
=> "sam@example.com"

irb> person.valid?
=> true

irb> person.persisted?
=> false

When we include ActiveModel::Model we get some features like:

  • Model name introspection
  • Conversions
  • Translations
  • Validations

Any class that includes ActiveModel::Model, can be used with Action View helper methods like form_with, render just like we do with Active Record objects.

Before

Before Rails 7, ActiveModel::Model works as the minimum API to talk with Action Pack and Action View.

However, the Model name suggests it can be included to create Active Record type models. But ActiveModel::Model does not support the basic common functionality ActiveModel::Attributes.

Let’s take the below example to see where the attribute: method fails.

class Person
  include ActiveModel::Model

  attribute :name, :string
  attribute :email, :string
end

NoMethodError (undefined method `attribute' for Person:Class)

To resolve the above issue, we need to include ActiveModel::Attributes in the Person class.

After

Starting with Rails 7 ActiveModel::Model’s implementation is moved to ActiveModel::API.

ActiveModel::API will now keep its definition to a minimum when talking with Action Pack and Action View. ActiveModel::Model can then be extended in the future to add more functionality that resembles ActiveRecord’s Model.

Note

ActiveModel::Model now only include ActiveModel::API. It enables the addition of more functionality to the Model while keeping things backward compatible.