AR BLOG
Active Record
1 What is Active Record?
Active Record is the M in MVC — the model — which is the layer of the system responsible for representing business data and logic. Active Record facilitates the creation and use of business objects whose data requires persistent storage to a database. It is an implementation of the Active Record pattern which itself is a description of an Object Relational Mapping system.
CRUD: Reading and Writing Data
CRUD is an acronym for the four verbs we use to operate on data: Create, Read, Update and Delete. Active Record automatically creates methods to allow an application to read and manipulate data stored within its tables.
Create
Active Record objects can be created from a hash, a block, or have their attributes manually set after creation. The new
method will return a new object while create
will return the object and save it to the database.
For example, given a model User
with attributes of name
and occupation
, the create
method call will create and save a new record into the database:
user = User.create(name: "David", occupation: "Code Artist")
Using the new
method, an object can be instantiated without being saved:
user = User.new
user.name = "David"
user.occupation = "Code Artist"
A call to user.save
will commit the record to the database.
Finally, if a block is provided, both create
and new
will yield the new object to that block for initialization:
user = User.new
do
|u|
u.name = "David"
u.occupation = "Code Artist"
end
Read
Active Record provides a rich API for accessing data within a database. Below are a few examples of different data access methods provided by Active Record.
# return a collection with all users
users = User.all
# return the first user
user = User.first
# return the first user named David
david = User.find_by(name: 'David')
# find all users named David who are Code Artists and sort by created_at in reverse chronological order
users = User.where(name: 'David', occupation: 'Code Artist').order(created_at: :desc)
Update
Once an Active Record object has been retrieved, its attributes can be modified and it can be saved to the database.
user = User.find_by(name: 'David')
user.name = 'Dave'
user.save
A shorthand for this is to use a hash mapping attribute names to the desired value, like so:
user = User.find_by(name: 'David')
user.update(name: 'Dave')
This is most useful when updating several attributes at once. If, on the other hand, you’d like to update several records in bulk, you may find the update_all
class method useful:
User.update_all "max_login_attempts = 3, must_change_password = 'true'"
Delete
Likewise, once retrieved an Active Record object can be destroyed which removes it from the database.
user = User.find_by(name: 'David')
user.destroy
If you’d like to delete several records in bulk, you may use destroy_by
or destroy_all
method:
# find and delete all users named David
User.destroy_by(name: 'David')
# delete all users
User.destroy_all
Validations
Active Record allows you to validate the state of a model before it gets written into the database. There are several methods that you can use to check your models and validate that an attribute value is not empty, is unique and not already in the database, follows a specific format, and many more.
Validation is a very important issue to consider when persisting to the database, so the methods save
and update
take it into account when running: they return false
when validation fails and they don't actually perform any operations on the database. All of these have a bang counterpart (that is, save!
and update!
), which are stricter in that they raise the exception ActiveRecord::RecordInvalid
if validation fails. A quick example to illustrate:
class
User < ApplicationRecord
validates :name, presence: true
end
user = User.new
user.save # => false
user.save! # => ActiveRecord::RecordInvalid: Validation failed: Name can't be blank
You can learn more about validations in the Active Record Validations guide.
Callbacks
Active Record callbacks allow you to attach code to certain events in the life-cycle of your models. This enables you to add behavior to your models by transparently executing code when those events occur, like when you create a new record, update it, destroy it, and so on.
Migrations
Rails provides a domain-specific language for managing a database schema called migrations. Migrations are stored in files which are executed against any database that Active Record supports using rake
. Here's a migration that creates a table:
class
CreatePublications < ActiveRecord::Migration[5.0]
def
change
create_table :publications
do
|t|
t.string :title
t.text :description
t.references :publication_type
t.integer :publisher_id
t.string :publisher_type
t.boolean :single_issue
t.timestamps
end
add_index :publications, :publication_type_id
end
end
Rails keeps track of which files have been committed to the database and provides rollback features. To actually create the table, you’d run rails db:migrate
and to roll it back, rails db:rollback
.
Note that the above code is database-agnostic: it will run in MySQL, PostgreSQL, Oracle, and others.
SQL
Ruby programs can interact with relational databases like MySQL via adapters in ActiveRecord. An adapter can be a pure Ruby implementation or a hybrid Ruby/C extension. From your Ruby code, you need to specify only the name of the adapter you want to use; ActiveRecord will provide the Ruby bridge code and worry about loading the native extension (if necessary).
MySQL is a one of the most popular open source databases around and is used by many prominent organizations from Yahoo to NASA.